Android Dialog, держать диалог открытым при нажатии кнопки

Я хотел бы сохранить мой диалог открытым, когда я нажимаю кнопку. На данный момент он закрывается.

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();

7 ответов

Решение

Да, ты можешь. Вам в основном нужно:

  1. Создать диалог с DialogBuilder
  2. показать () диалог
  3. Найдите кнопки в показанном диалоге и переопределите их onClickListener

Итак, создайте класс слушателя:

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

Тогда при показе диалога используйте:

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

Помните, что вам нужно показать диалоговое окно, иначе кнопка не будет доступна для поиска. Кроме того, обязательно измените DialogInterface.BUTTON_POSITIVE на любое значение, которое вы использовали для добавления кнопки. Также обратите внимание, что при добавлении кнопок в DialogBuilder вам нужно будет предоставить onClickListeners - вы не можете добавить туда настраиваемого слушателя - диалог все равно будет отклонен, если вы не переопределите слушателей после show() называется.

Спасибо Sogger за ваш ответ, но есть одно изменение, которое мы должны сделать здесь: перед тем, как создавать диалог, мы должны установить для AlertDialog возможную кнопку (и отрицательную кнопку, если есть необходимость) традиционным способом.

Ссылка на Sogger.

Вот пример примера...

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

Я считаю, что ответ @Kamen правильный, вот пример того же подхода, использующего вместо этого анонимный класс, поэтому он все в одном потоке кода:

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

Я написал более подробное описание, чтобы ответить на тот же вопрос здесь /questions/6244838/kak-predotvratit-zakryitie-dialoga-pri-nazhatii-knopki/6244855#6244855 котором также есть примеры для других диалогов, таких как DialogFragment и DialogPreference.

Вот как мне удается создать постоянное всплывающее окно при смене пароля.

// 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 ();
    }
}

Кстати, я использую Mono для Android, а не Eclipse.

Вам не нужно создавать пользовательский класс. Вы можете зарегистрировать View.OnClickListener для AlertDialog. Этот слушатель не уволит AlertDialog. Хитрость заключается в том, что вам нужно зарегистрировать слушателя после того, как диалоговое окно было показано, но это можно сделать аккуратно внутри OnShowListener. Вы можете использовать вспомогательную логическую переменную, чтобы проверить, было ли это уже сделано, так что это будет сделано только один раз:

/*
 * 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;
        }
    }
});

Вам, вероятно, потребуется определить свой собственный макет и не использовать "официальные" кнопки; поведение, которое вы просите, не типично для диалога.

Вы можете получить диалог, возвращенный методом "show()" alertBuidler.

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

Вызовите метод "show ()" для adb и получите диалог

final AlertDialog dialog = adb.show();

Таким образом, вы можете вызвать любую кнопку вашего диалога в любой точке кода вашей активности:

dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();//or
dialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick();//or
dialog.getButton(DialogInterface.BUTTON_NEUTRAL).performClick();
Другие вопросы по тегам