web-dev-qa-db-de.com

Android-Dialog: Lassen Sie den Dialog geöffnet, wenn Sie die Taste drücken

Ich möchte meinen Dialog offen halten, wenn ich einen Knopf drücke ... Im Moment schließt er.

AlertDialog.Builder builder = new AlertDialog.Builder(this);

builder.setMessage("Are you sure you want to exit?")

   .setCancelable(false)
   .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
       public void onClick(DialogInterface dialog, int id) {
            MyActivity.this.finish();
       }
   })
   .setNegativeButton("No", new DialogInterface.OnClickListener() {
       public void onClick(DialogInterface dialog, int id) {
            dialog.cancel();
       }
   });
AlertDialog alert = builder.create();
61
Sebastian

Ja, du kannst. Sie müssen grundsätzlich:

  1. Erstellen Sie den Dialog mit DialogBuilder
  2. show () den Dialog
  3. Finden Sie die Schaltflächen im angezeigten Dialog und überschreiben Sie deren onClickListener

Erstellen Sie also eine Listener-Klasse:

class CustomListener implements View.OnClickListener {
  private final Dialog dialog;

  public CustomListener(Dialog dialog) {
    this.dialog = dialog;
  }

  @Override
  public void onClick(View v) {

    // Do whatever you want here

    // If you want to close the dialog, uncomment the line below
    //dialog.dismiss();
  }
}

Verwenden Sie dann beim Anzeigen des Dialogs:

AlertDialog dialog = dialogBuilder.create();
dialog.show();
Button theButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
theButton.setOnClickListener(new CustomListener(dialog));

Denken Sie daran, dass Sie den Dialog anzeigen müssen, andernfalls kann die Schaltfläche nicht gefunden werden. Stellen Sie außerdem sicher, dass Sie DialogInterface.BUTTON_POSITIVE in den Wert setzen, den Sie zum Hinzufügen der Schaltfläche verwendet haben. Beachten Sie auch, dass beim Hinzufügen der Schaltflächen in DialogBuilder Sie onClickListeners angeben müssen - Sie können jedoch nicht den benutzerdefinierten Listener dort hinzufügen. - Das Dialogfeld wird trotzdem geschlossen, wenn Sie die Listener nicht überschreiben, nachdem show() aufgerufen wurde.

91
Kamen

Vielen Dank Sogger für Ihre Antwort, aber es gibt eine Änderung, die wir hier vornehmen müssen. Bevor Sie ein Dialogfeld erstellen, sollten Sie die Optionstaste (und die Negativtaste, falls dies erforderlich ist) auf AlertDialog wie üblich setzen. 

Von Sogger referenziert.

Hier ist das Beispielbeispiel ...  

AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Test for preventing dialog close");
        builder.setTitle("Test");

        builder.setPositiveButton("OK", new OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub

            }
        });
    builder.setNegativeButton("Cancel", new OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub

            }
        });

        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.
                  }
              });

        dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener()
          {            
              @Override
              public void onClick(View v)
              {
                  Boolean wantToCloseDialog = true;
                  //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.
              }
          });
28
Shailesh

Ich glaube, die Antwort von @Kamen ist korrekt. Hier ist ein Beispiel für denselben Ansatz, der stattdessen eine anonyme Klasse verwendet, sodass alles in einem einzigen Codestrom enthalten ist:

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Test for preventing dialog close");
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)
                  dismiss();
              //else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
          }
      });

Ich habe eine ausführlichere Beschreibung geschrieben, um dieselbe Frage hier zu beantworten https://stackoverflow.com/a/15619098/579234 , die auch Beispiele für andere Dialoge wie DialogFragment und DialogPreference enthält.

13
Sogger

So schaffe ich es, beim Ändern eines Passworts ein beständiges Popup zu erstellen.

// Login Activity
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.SetIcon(Resource.Drawable.padlock);
alert.SetCancelable(false);

var changepass = LayoutInflater.From(this);
var changePassLayout = changepass.Inflate(Resource.Layout.ChangePasswordLayout, null);

alert.SetView(changePassLayout);

txtChangePassword = (EditText)changePassLayout.FindViewById(Resource.Id.txtChangePassword);
txtChangeRetypePassword = (EditText)changePassLayout.FindViewById(Resource.Id.txtChangeRetypePassword);

alert.SetPositiveButton("Change", delegate {
    // You can leave this blank because you override the OnClick event using your custom listener
});

alert.SetNegativeButton("Cancel", delegate {
    Toast.MakeText(this, "Change password aborted!", ToastLength.Short).Show();
});

AlertDialog changePassDialog = alert.Create();
changePassDialog.Show();

// Override OnClick of Positive Button
Button btnPositive = changePassDialog.GetButton((int)Android.Content.DialogButtonType.Positive);
btnPositive.SetOnClickListener(new CustomListener(changePassDialog, empDetailsToValidate.EmployeeID));

// My Custom Class
class CustomListener : Java.Lang.Object, View.IOnClickListener, IDialogInterfaceOnDismissListener
{
    AlertDialog _dialog;
    EditText txtChangePassword;
    EditText txtChangeRetypePassword;

    EmployeeDetails _empDetails;
    string _workingEmployeeID;

    public CustomListener(AlertDialog dialog, string employeeID)
    {
        this._dialog = dialog;
        this._workingEmployeeID = employeeID;
    }
    public void OnClick (View v)
    {
        _empDetails = new EmployeeDetails(v.Context);

        txtChangePassword = (EditText)_dialog.FindViewById (Resource.Id.txtChangePassword);
        txtChangeRetypePassword = (EditText)_dialog.FindViewById (Resource.Id.txtChangeRetypePassword);

        if (!(txtChangePassword.Text.Equals(txtChangeRetypePassword.Text))) {
            Show ();
            Toast.MakeText(v.Context, "Password not match.", ToastLength.Short).Show();
        } else if (txtChangePassword.Text.Trim().Length < 6) {
            Show ();
            Toast.MakeText(v.Context, "Minimum password length is 6 characters.", ToastLength.Short).Show();
        } else if ((txtChangePassword.Text.Equals(LoginActivity.defaultPassword)) || (txtChangePassword.Text == "" || txtChangeRetypePassword.Text == "")) {
            Show ();
            Toast.MakeText(v.Context, "Invalid password. Please use other password.", ToastLength.Short).Show();
        } else {
            int rowAffected = _empDetails.UpdatePassword(_workingEmployeeID, SensoryDB.PassCrypto(txtChangePassword.Text, true));
            if (rowAffected > 0) {
                Toast.MakeText(v.Context, "Password successfully changed!", ToastLength.Short).Show();
                _dialog.Dismiss();
            } else {
                Toast.MakeText(v.Context, "Cant update password!", ToastLength.Short).Show();
                Show();
            }
        }
    }
    public void OnDismiss (IDialogInterface dialog)
    {
        if (!(txtChangePassword.Text.Equals (txtChangePassword.Text))) {
            Show ();
        } else {
            _dialog.Dismiss();
        }
    }
    public void Show ()
    {
        _dialog.Show ();
    }
}

Übrigens, ich benutze Mono für Android nicht Eclipse.

2
klaydze

Sie müssen keine benutzerdefinierte Klasse erstellen. Sie können einen View.OnClickListener für den AlertDialog registrieren. Dieser Listener wird den AlertDialog nicht abweisen. Der Trick hier ist, dass Sie den Listener registrieren müssen, nachdem das Dialogfeld angezeigt wurde. Dies kann jedoch problemlos in einem OnShowListener durchgeführt werden. Sie können eine zusätzliche boolesche Variable verwenden, um zu prüfen, ob dies bereits geschehen ist, sodass dies nur einmal erfolgt:

/*
 * Prepare the alert with a Builder.
 */
AlertDialog.Builder b = new AlertDialog.Builder(this);

b.setNegativeButton("Button", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {}
});
this.alert = b.create();

/*
 * Add an OnShowListener to change the OnClickListener on the
 * first time the alert is shown. Calling getButton() before
 * the alert is shown will return null. Then use a regular
 * View.OnClickListener for the button, which will not 
 * dismiss the AlertDialog after it has been called.
 */

this.alertReady = false;
alert.setOnShowListener(new DialogInterface.OnShowListener() {
    @Override
    public void onShow(DialogInterface dialog) {
        if (alertReady == false) {
            Button button = alert.getButton(DialogInterface.BUTTON_NEGATIVE);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //do something
                }
            });
            alertReady = true;
        }
    }
});
0
user7960788

Sie müssen wahrscheinlich Ihr eigenes Layout definieren und nicht die "offiziellen" Schaltflächen verwenden. Das Verhalten, nach dem Sie fragen, ist nicht typisch für ein Dialogfeld.

0
mah

Sie können den Dialog von der Methode "show ()" alertBuidler zurückgeben.

AlertDialog.Builder adb = new AlertDialog.Builder(YourActivity.this);
//...code to add methods setPositive an setNegative buttons

Rufen Sie die "show ()" Methode von "adb" auf und rufen Sie den Dialog auf

final AlertDialog dialog = adb.show();

Sie können also an jeder Stelle Ihres Codes eine beliebige Schaltfläche Ihres Dialogs aufrufen:

dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();//or
dialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick();//or
dialog.getButton(DialogInterface.BUTTON_NEUTRAL).performClick();
0
Romeryto