Hier sind einige Lösungen für alle Arten von Dialogen, einschließlich einer Lösung für AlertDialog.Builder, die auf allen API-Ebenen funktioniert (funktioniert unter API 8, was die andere Antwort hier nicht tut). Es gibt Lösungen für AlertDialogs mit AlertDialog.Builder, DialogFragment und DialogPreference.
Im Folgenden finden Sie Codebeispiele, die zeigen, wie Sie den Standardhandler für allgemeine Schaltflächen überschreiben und verhindern, dass der Dialog für diese verschiedenen Formen von Dialogen geschlossen wird. Alle Beispiele zeigen, wie verhindert wird, dass die positive Schaltfläche den Dialog schließt.
Hinweis: Eine Beschreibung, wie das Schließen des Dialogfelds unter der Haube für die Basis-Android-Klassen funktioniert und warum die folgenden Ansätze ausgewählt werden, folgt nach den Beispielen für diejenigen, die weitere Details wünschen
AlertDialog.Builder - Ändert den Standard-Button-Handler unmittelbar nach show ()
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Test for preventing dialog close");
builder.setPositiveButton("Test",
new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
//Do nothing here because we override this button later to change the close behaviour.
//However, we still need this because on older versions of Android unless we
//pass a handler the button doesn't get instantiated
}
});
final AlertDialog dialog = builder.create();
dialog.show();
//Overriding the handler immediately after show is probably a better approach than OnShowListener as described below
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Boolean wantToCloseDialog = false;
//Do stuff, possibly set wantToCloseDialog to true then...
if(wantToCloseDialog)
dialog.dismiss();
//else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
}
});
DialogFragment - überschreibe onResume ()
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Test for preventing dialog close");
builder.setPositiveButton("Test",
new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
//Do nothing here because we override this button later to change the close behaviour.
//However, we still need this because on older versions of Android unless we
//pass a handler the button doesn't get instantiated
}
});
return builder.create();
}
//onStart() is where dialog.show() is actually called on
//the underlying dialog, so we have to do it there or
//later in the lifecycle.
//Doing it in onResume() makes sure that even if there is a config change
//environment that skips onStart then the dialog will still be functioning
//properly after a rotation.
@Override
public void onResume()
{
super.onResume();
final AlertDialog d = (AlertDialog)getDialog();
if(d != null)
{
Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Boolean wantToCloseDialog = false;
//Do stuff, possibly set wantToCloseDialog to true then...
if(wantToCloseDialog)
d.dismiss();
//else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
}
});
}
}
DialogPreference - überschreibe showDialog ()
@Override
protected void onPrepareDialogBuilder(Builder builder)
{
super.onPrepareDialogBuilder(builder);
builder.setPositiveButton("Test", this); //Set the button here so it gets created
}
@Override
protected void showDialog(Bundle state)
{
super.showDialog(state); //Call show on default first so we can override the handlers
final AlertDialog d = (AlertDialog) getDialog();
d.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Boolean wantToCloseDialog = false;
//Do stuff, possibly set wantToCloseDialog to true then...
if(wantToCloseDialog)
d.dismiss();
//else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
}
});
}
Erklärung der Ansätze:
Beim Durchsuchen des Android-Quellcodes registriert die Standardimplementierung von AlertDialog einen gemeinsamen Schaltflächenhandler für alle tatsächlichen Schaltflächen in OnCreate (). Wenn auf eine Schaltfläche geklickt wird, leitet der allgemeine Schaltflächenhandler das Klickereignis an den Handler weiter, den Sie in setButton () übergeben haben, und ruft dann den Dialog ab.
Wenn Sie verhindern möchten, dass ein Dialogfeld geschlossen wird, wenn eine dieser Schaltflächen gedrückt wird, müssen Sie den allgemeinen Schaltflächenhandler für die tatsächliche Ansicht der Schaltfläche ersetzen. Da es in OnCreate () zugewiesen ist, müssen Sie es ersetzen, nachdem die Standardimplementierung von OnCreate () aufgerufen wurde. OnCreate wird im Verlauf der show () -Methode aufgerufen. Sie können eine benutzerdefinierte Dialogklasse erstellen und OnCreate () überschreiben, um super.OnCreate () aufzurufen, und dann die Schaltflächenhandler überschreiben. Wenn Sie jedoch ein benutzerdefiniertes Dialogfeld erstellen, erhalten Sie den Builder nicht kostenlos. In diesem Fall geht es darum ?
Wenn Sie ein Dialogfeld so verwenden, wie es entworfen wurde, aber steuern, wann es geschlossen wird, besteht ein Ansatz darin, zuerst dialog.Show () aufzurufen und dann mithilfe von dialog.getButton () einen Verweis auf die Schaltfläche abzurufen, um den Klick-Handler zu überschreiben. Ein anderer Ansatz besteht darin, setOnShowListener () zu verwenden und das Suchen der Schaltflächenansicht und das Ersetzen des Handlers im OnShowListener zu implementieren. Der funktionale Unterschied zwischen den beiden ist "fast" gleich Null, je nachdem, welcher Thread ursprünglich die Dialoginstanz erstellt. Beim Durchsuchen des Quellcodes wird der onShowListener von einer Nachricht aufgerufen, die an einen Handler gesendet wird, der in dem Thread ausgeführt wird, der diesen Dialog erstellt hat. Da Ihr OnShowListener von einer in der Nachrichtenwarteschlange geposteten Nachricht aufgerufen wird, ist es technisch möglich, dass sich der Anruf Ihres Listeners einige Zeit nach Abschluss der Show verzögert.
Daher glaube ich, dass der sicherste Ansatz der erste ist: show.Dialog () aufrufen und dann sofort im selben Ausführungspfad die Schaltflächenhandler ersetzen. Da Ihr Code, der show () aufruft, auf dem Haupt-GUI-Thread ausgeführt wird, bedeutet dies, dass der Code, dem Sie show () folgen, vor jedem anderen Code in diesem Thread ausgeführt wird, während das Timing der OnShowListener-Methode von abhängig ist die Nachrichtenwarteschlange.