Как предотвратить закрытие диалогового окна при нажатии кнопки

У меня есть диалог с EditText для ввода. Когда я нажимаю кнопку «Да» в диалоговом окне, он проверяет ввод и закрывает диалоговое окно. Однако, если вход неверный, я хочу оставаться в том же диалоговом окне. Каждый раз, независимо от ввода, диалог должен автоматически закрываться, когда я нажимаю кнопку «Нет». Как я могу отключить это? Кстати, я использовал PositiveButton и NegativeButton для кнопки в диалоговом окне.

EDIT: Это работает только на API 8+, как отмечено некоторыми комментариями.

Это поздний ответ, но вы можете добавить onShowListener в AlertDialog, где вы можете переопределить onClickListener кнопки.

 final AlertDialog dialog = new AlertDialog.Builder(context) .setView(v) .setTitle(R.string.my_title) .setPositiveButton(android.R.string.ok, null) //Set to null. We override the onclick .setNegativeButton(android.R.string.cancel, null) .create(); dialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // TODO Do something //Dismiss once everything is OK. dialog.dismiss(); } }); } }); 

Ниже приведены некоторые решения для всех типов диалогов, включая решение для AlertDialog.Builder, которое будет работать на всех уровнях API (работает ниже API 8, чего нет в другом ответе). Существуют решения для AlertDialogs с использованием AlertDialog.Builder, DialogFragment и DialogPreference.

Ниже приведены примеры кода, показывающие, как переопределить стандартный обработчик кнопок и запретить закрытие диалога для этих разных форм диалогов. Все примеры показывают, как предотвратить закрытие диалогового окна положительной кнопкой.

Примечание: описание того, как закрытие диалога работает под капотом для базовых классов андроида и почему следующие подходы выбираются, следует за примерами, для тех, кто хочет получить более подробную информацию


AlertDialog.Builder – изменить обработчик кнопки по умолчанию сразу после 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 – переопределить 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 – переопределить 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. } }); } 

Объяснение подходов:

Изучая исходный код Android, реализация AlertDialog по умолчанию работает, регистрируя общий обработчик кнопок для всех реальных кнопок в OnCreate (). Когда нажимается кнопка, общий обработчик кнопки пересылает событие клика любому обработчику, который вы передали в setButton (), а затем вызывает отклонение диалога.

Если вы хотите запретить закрытие диалогового окна при нажатии одной из этих кнопок, вы должны заменить обычный обработчик кнопок для фактического просмотра кнопки. Поскольку он назначен в OnCreate (), вы должны заменить его после вызова по умолчанию OnCreate (). OnCreate вызывается в процессе метода show (). Вы можете создать пользовательский класс Dialog и переопределить OnCreate (), чтобы вызвать super.OnCreate (), затем переопределить обработчики кнопок, но если вы создадите собственный диалог, вы не получите Builder бесплатно, и в этом случае какая точка ?

Таким образом, при использовании диалога, как он разработан, но с контролем при его увольнении, одним из подходов является вызов dialog.Show (), а затем получение ссылки на кнопку с помощью dialog.getButton () для переопределения обработчика кликов. Другой подход – использовать setOnShowListener () и реализовать поиск кнопки и замену обработчика в OnShowListener. Функциональное различие между ними – «почти», в зависимости от того, какой поток изначально создает экземпляр диалога. Просматривая исходный код, onShowListener вызывается сообщением, отправленным обработчику, запущенному в потоке, который создал этот диалог. Итак, поскольку ваш OnShowListener вызывается сообщением, размещенным в очереди сообщений, технически возможно, что вызов вашего слушателя задерживается через некоторое время после завершения шоу.

Поэтому я считаю, что самый безопасный подход является первым: вызвать show.Dialog (), а затем сразу же в том же пути выполнить замену обработчиков кнопок. Поскольку ваш код, вызывающий show (), будет работать в главном потоке графического интерфейса, это означает, что любой код, которым вы следуете show (), будет выполняться перед любым другим кодом в этом потоке, тогда как время метода OnShowListener находится во власти Очередь сообщений.

Я написал простой класс (AlertDialogBuilder), который можно использовать для отключения функции автоматического увольнения при нажатии кнопок диалога.

Он также совместим с Android 1.6, поэтому он не использует OnShowListener (который доступен только API> = 8).

Таким образом, вместо использования AlertDialog.Builder вы можете использовать этот CustomAlertDialogBuilder. Самой важной частью является то, что вы не должны вызывать create () , а только метод show () . Я добавил такие методы, как setCanceledOnTouchOutside () и setOnDismissListener, так что вы все равно можете установить их непосредственно в построителе.

Я тестировал его на Android 1.6, 2.x, 3.x и 4.x, поэтому он должен работать очень хорошо. Если вы обнаружите некоторые проблемы, прокомментируйте здесь.

 package com.droidahead.lib.utils; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.view.View; import android.view.View.OnClickListener; public class CustomAlertDialogBuilder extends AlertDialog.Builder { /** * Click listeners */ private DialogInterface.OnClickListener mPositiveButtonListener = null; private DialogInterface.OnClickListener mNegativeButtonListener = null; private DialogInterface.OnClickListener mNeutralButtonListener = null; /** * Buttons text */ private CharSequence mPositiveButtonText = null; private CharSequence mNegativeButtonText = null; private CharSequence mNeutralButtonText = null; private DialogInterface.OnDismissListener mOnDismissListener = null; private Boolean mCancelOnTouchOutside = null; public CustomAlertDialogBuilder(Context context) { super(context); } public CustomAlertDialogBuilder setOnDismissListener (DialogInterface.OnDismissListener listener) { mOnDismissListener = listener; return this; } @Override public CustomAlertDialogBuilder setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener) { mNegativeButtonListener = listener; mNegativeButtonText = text; return this; } @Override public CustomAlertDialogBuilder setNeutralButton(CharSequence text, DialogInterface.OnClickListener listener) { mNeutralButtonListener = listener; mNeutralButtonText = text; return this; } @Override public CustomAlertDialogBuilder setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener) { mPositiveButtonListener = listener; mPositiveButtonText = text; return this; } @Override public CustomAlertDialogBuilder setNegativeButton(int textId, DialogInterface.OnClickListener listener) { setNegativeButton(getContext().getString(textId), listener); return this; } @Override public CustomAlertDialogBuilder setNeutralButton(int textId, DialogInterface.OnClickListener listener) { setNeutralButton(getContext().getString(textId), listener); return this; } @Override public CustomAlertDialogBuilder setPositiveButton(int textId, DialogInterface.OnClickListener listener) { setPositiveButton(getContext().getString(textId), listener); return this; } public CustomAlertDialogBuilder setCanceledOnTouchOutside (boolean cancelOnTouchOutside) { mCancelOnTouchOutside = cancelOnTouchOutside; return this; } @Override public AlertDialog create() { throw new UnsupportedOperationException("CustomAlertDialogBuilder.create(): use show() instead.."); } @Override public AlertDialog show() { final AlertDialog alertDialog = super.create(); DialogInterface.OnClickListener emptyOnClickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }; // Enable buttons (needed for Android 1.6) - otherwise later getButton() returns null if (mPositiveButtonText != null) { alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, mPositiveButtonText, emptyOnClickListener); } if (mNegativeButtonText != null) { alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, mNegativeButtonText, emptyOnClickListener); } if (mNeutralButtonText != null) { alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, mNeutralButtonText, emptyOnClickListener); } // Set OnDismissListener if available if (mOnDismissListener != null) { alertDialog.setOnDismissListener(mOnDismissListener); } if (mCancelOnTouchOutside != null) { alertDialog.setCanceledOnTouchOutside(mCancelOnTouchOutside); } alertDialog.show(); // Set the OnClickListener directly on the Button object, avoiding the auto-dismiss feature // IMPORTANT: this must be after alert.show(), otherwise the button doesn't exist.. // If the listeners are null don't do anything so that they will still dismiss the dialog when clicked if (mPositiveButtonListener != null) { alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mPositiveButtonListener.onClick(alertDialog, AlertDialog.BUTTON_POSITIVE); } }); } if (mNegativeButtonListener != null) { alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mNegativeButtonListener.onClick(alertDialog, AlertDialog.BUTTON_NEGATIVE); } }); } if (mNeutralButtonListener != null) { alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mNeutralButtonListener.onClick(alertDialog, AlertDialog.BUTTON_NEUTRAL); } }); } return alertDialog; } } 

EDIT Вот небольшой пример того, как использовать CustomAlertDialogBuilder:

 // Create the CustomAlertDialogBuilder CustomAlertDialogBuilder dialogBuilder = new CustomAlertDialogBuilder(context); // Set the usual data, as you would do with AlertDialog.Builder dialogBuilder.setIcon(R.drawable.icon); dialogBuilder.setTitle("Dialog title"); dialogBuilder.setMessage("Some text.."); // Set your buttons OnClickListeners dialogBuilder.setPositiveButton ("Button 1", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int which) { // Do something... // Dialog will not dismiss when the button is clicked // call dialog.dismiss() to actually dismiss it. } }); // By passing null as the OnClickListener the dialog will dismiss when the button is clicked. dialogBuilder.setNegativeButton ("Close", null); // Set the OnDismissListener (if you need it) dialogBuilder.setOnDismissListener(new DialogInterface.OnDismissListener() { public void onDismiss(DialogInterface dialog) { // dialog was just dismissed.. } }); // (optional) set whether to dismiss dialog when touching outside dialogBuilder.setCanceledOnTouchOutside(false); // Show the dialog dialogBuilder.show(); 

Ура,

Yuvi

Вот что-то, если вы используете DialogFragment – это рекомендуемый способ обработки Dialogs.

Что происходит с методом setButton() и я предполагаю, что с setPositiveButton() и setNegativeButton() ) setNegativeButton() является то, что кнопка, которую вы установили (например, AlertDialog.BUTTON_POSITIVE ), будет фактически инициировать два разных объекта OnClickListener при нажатии.

Первым из них является DialogInterface.OnClickListener , который является параметром setButton() , setPositiveButton() и setNegativeButton() .

Другой – View.OnClickListener , который будет настроен на автоматическое отклонение вашего AlertDialog при нажатии любой из его кнопок – и устанавливается самим AlertDialog .

Вы можете использовать setButton() с null как DialogInterface.OnClickListener , чтобы создать кнопку, а затем вызвать свой собственный метод действий внутри View.OnClickListener . Например,

 @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog alertDialog = new AlertDialog(getActivity()); // set more items... alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", null); return alertDialog; } 

Затем вы можете переопределить кнопки View.OnClickListener по умолчанию « View.OnClickListener (который иначе DialogFragment диалог) в DialogFragment onResume() :

 @Override public void onResume() { super.onResume(); AlertDialog alertDialog = (AlertDialog) getDialog(); Button okButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); okButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { performOkButtonAction(); } }); } private void performOkButtonAction() { // Do your stuff here } 

Вам нужно будет установить это в onResume() потому что getButton() вернет значение null до тех пор, пока не появится диалог!

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

Вдохновленный ответом Тома, я считаю, что идея здесь такова:

  • Установите onClickListener во время создания диалогового окна с null
  • Затем установите onClickListener после onClickListener диалогового окна.

Вы можете переопределить onShowListener как Том. Кроме того, вы можете

  1. Получить кнопку после вызова show() AlertDialog show()
  2. Установите кнопки onClickListener следующим образом (немного более читаемым, я думаю).

Код:

 AlertDialog.Builder builder = new AlertDialog.Builder(context); // ... final AlertDialog dialog = builder.create(); dialog.show(); // now you can override the default onClickListener Button b = dialog.getButton(AlertDialog.BUTTON_POSITIVE); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Log.i(TAG, "ok button is clicked"); handleClick(dialog); } }); 

Для pre API 8 я решил проблему с использованием логического флага, увольнения слушателя и вызова dialog.show снова, если в случае, если содержимое editText не было правильно. Как это:

 case ADD_CLIENT: LayoutInflater factoryClient = LayoutInflater.from(this); final View EntryViewClient = factoryClient.inflate( R.layout.alert_dialog_add_client, null); EditText ClientText = (EditText) EntryViewClient .findViewById(R.id.client_edit); AlertDialog.Builder builderClient = new AlertDialog.Builder(this); builderClient .setTitle(R.string.alert_dialog_client) .setCancelable(false) .setView(EntryViewClient) .setPositiveButton("Save", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { EditText newClient = (EditText) EntryViewClient .findViewById(R.id.client_edit); String newClientString = newClient .getText().toString(); if (checkForEmptyFields(newClientString)) { //If field is empty show toast and set error flag to true; Toast.makeText(getApplicationContext(), "Fields cant be empty", Toast.LENGTH_SHORT).show(); add_client_error = true; } else { //Here save the info and set the error flag to false add_client_error = false; } } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { add_client_error = false; dialog.cancel(); } }); final AlertDialog alertClient = builderClient.create(); alertClient.show(); alertClient .setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { //If the error flag was set to true then show the dialog again if (add_client_error == true) { alertClient.show(); } else { return; } } }); return true; 

Ответ по этой ссылке является простым решением и совместимым с API 3. Он очень похож на решение Tom Bollwitt, но без использования менее совместимого OnShowListener.

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

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

Я внес небольшие изменения в код Камена, так как я расширил EditTextPreference.

 @Override protected void showDialog(Bundle state) { super.showDialog(state); class mocl implements OnClickListener{ private final AlertDialog dialog; public mocl(AlertDialog dialog) { this.dialog = dialog; } @Override public void onClick(View v) { //checks if EditText is empty, and if so tells the user via Toast //otherwise it closes dialog and calls the EditTextPreference's onClick //method to let it know that the button has been pressed if (!IntPreference.this.getEditText().getText().toString().equals("")){ dialog.dismiss(); IntPreference.this.onClick(dialog,DialogInterface.BUTTON_POSITIVE); } else { Toast t = Toast.makeText(getContext(), "Enter a number!", Toast.LENGTH_SHORT); t.show(); } } } AlertDialog d = (AlertDialog) getDialog(); Button b = d.getButton(DialogInterface.BUTTON_POSITIVE); b.setOnClickListener(new mocl((d))); } 

Так весело!

Альтернативное решение

Я хотел бы представить альтернативный ответ с точки зрения UX.

Почему вы хотите предотвратить закрытие диалогового окна при нажатии кнопки? Предположительно, это потому, что у вас есть пользовательский диалог, в котором пользователь не сделал выбор или еще не полностью заполнил все. И если они еще не закончены, вы не должны позволять им нажимать кнопку «положительный». Просто отключите его, пока все не будет готово.

Другие ответы здесь дают много трюков для переопределения положительного нажатия кнопки. Если бы это было важно, разве Android не сделал бы удобный способ сделать это? Они этого не сделали.

Вместо этого в руководстве по дизайну Dialogs показан пример такой ситуации. Кнопка OK отключена, пока пользователь не сделает выбор. Никаких дополнительных приемов вообще не требуется. Очевидно, что что-то еще нужно сделать, прежде чем продолжать.

Введите описание изображения здесь

Как отключить положительную кнопку

См. Документацию по Android для создания настраиваемого диалогового макета . Он рекомендует разместить AlertDialog внутри DialogFragment . Затем все, что вам нужно сделать, – установить слушатели на элементах макета, чтобы знать, когда включать или отключать положительную кнопку.

  • Если в пользовательском диалоге есть переключатели, используйте RadioGroup.OnCheckedChangeListener .
  • Если в вашем пользовательском диалоговом окне установлены флажки, используйте CompoundButton.OnCheckedChangeListener .
  • Если ваш пользовательский диалог имеет EditText , используйте TextWatcher .

Положительную кнопку можно отключить следующим образом:

 AlertDialog dialog = (AlertDialog) getDialog(); dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); 

Вот полный рабочий DialogFragment с отключенной положительной кнопкой, например, которая может быть использована на изображении выше.

 import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; public class MyDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // inflate the custom dialog layout LayoutInflater inflater = getActivity().getLayoutInflater(); View view = inflater.inflate(R.layout.my_dialog_layout, null); // add a listener to the radio buttons RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.radio_group); radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup radioGroup, int i) { // enable the positive button after a choice has been made AlertDialog dialog = (AlertDialog) getDialog(); dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); } }); // build the alert dialog AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setView(view) .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { // TODO: use an interface to pass the user choice back to the activity } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MyDialogFragment.this.getDialog().cancel(); } }); return builder.create(); } @Override public void onResume() { super.onResume(); // disable positive button by default AlertDialog dialog = (AlertDialog) getDialog(); dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); } } 

Пользовательский диалог можно запустить из такой активности:

 MyDialogFragment dialog = new MyDialogFragment(); dialog.show(getFragmentManager(), "MyTag"); 

Заметки

  • Для краткости я пропустил интерфейс связи, чтобы передать информацию о выборе пользователя обратно в действие. Однако документация показывает, как это делается.
  • Кнопка по-прежнему не onCreateDialog в onCreateDialog поэтому я отключил ее в onResume . Это приводит к нежелательному эффекту отключения его снова, если пользователь переключается на другое приложение, а затем возвращается без отклонения диалога. Это можно было бы решить, не onCreateDialog выбор пользователя или вызывая Runnable из onCreateDialog чтобы отключить кнопку в следующем цикле запуска.

     view.post(new Runnable() { @Override public void run() { AlertDialog dialog = (AlertDialog) getDialog(); dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); } }); 

Этот код будет работать для вас, потому что у меня была близкая проблема, и это сработало для меня. 🙂

1- Переопределить метод Onstart () в классе фрагмента-диалога.

 @Override public void onStart() { super.onStart(); final AlertDialog D = (AlertDialog) getDialog(); if (D != null) { Button positive = (Button) D.getButton(Dialog.BUTTON_POSITIVE); positive.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { if (edittext.equals("")) { Toast.makeText(getActivity(), "EditText empty",Toast.LENGTH_SHORT).show(); } else { D.dismiss(); //dissmiss dialog } } }); } } 

Вероятно, это очень поздний ответ, но использование setCancelable сделает трюк.

 alertDial.setCancelable(false); 

Для ProgressDialogs

Чтобы предотвратить автоматическое отключение диалога, вы должны установить OnClickListener после OnClickListener ProgressDialog , например:

 connectingDialog = new ProgressDialog(this); connectingDialog.setCancelable(false); connectingDialog.setCanceledOnTouchOutside(false); // Create the button but set the listener to a null object. connectingDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", (DialogInterface.OnClickListener) null ) // Show the dialog so we can then get the button from the view. connectingDialog.show(); // Get the button from the view. Button dialogButton = connectingDialog.getButton( DialogInterface.BUTTON_NEGATIVE); // Set the onClickListener here, in the view. dialogButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick ( View v ) { // Dialog will not get dismissed until you call dismiss() explicitly. } }); 
 public class ComentarDialog extends DialogFragment{ private EditText comentario; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); LayoutInflater inflater = LayoutInflater.from(getActivity()); View v = inflater.inflate(R.layout.dialog_comentar, null); comentario = (EditText)v.findViewById(R.id.etxt_comentar_dialog); builder.setTitle("Comentar") .setView(v) .setPositiveButton("OK", null) .setNegativeButton("CANCELAR", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { } }); return builder.create(); } @Override public void onStart() { super.onStart(); //Obtenemos el AlertDialog AlertDialog dialog = (AlertDialog)getDialog(); dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false);//Al presionar atras no desaparece //Implementamos el listener del boton OK para mostrar el toast dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(TextUtils.isEmpty(comentario.getText())){ Toast.makeText(getActivity(), "Ingrese un comentario", Toast.LENGTH_SHORT).show(); return; } else{ ((AlertDialog)getDialog()).dismiss(); } } }); //Personalizamos Resources res = getResources(); //Buttons Button positive_button = dialog.getButton(DialogInterface.BUTTON_POSITIVE); positive_button.setBackground(res.getDrawable(R.drawable.btn_selector_dialog)); Button negative_button = dialog.getButton(DialogInterface.BUTTON_NEGATIVE); negative_button.setBackground(res.getDrawable(R.drawable.btn_selector_dialog)); int color = Color.parseColor("#304f5a"); //Title int titleId = res.getIdentifier("alertTitle", "id", "android"); View title = dialog.findViewById(titleId); if (title != null) { ((TextView) title).setTextColor(color); } //Title divider int titleDividerId = res.getIdentifier("titleDivider", "id", "android"); View titleDivider = dialog.findViewById(titleDividerId); if (titleDivider != null) { titleDivider.setBackgroundColor(res.getColor(R.color.list_menu_divider)); } } } 

Вы можете добавить builder.show (); После подтверждения сообщения перед возвратом;

как это

  public void login() { final AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setView(R.layout.login_layout); builder.setTitle("Login"); builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } });// put the negative button before the positive button, so it will appear builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { Dialog d = (Dialog) dialog; final EditText etUserName = (EditText) d.findViewById(R.id.etLoginName); final EditText etPassword = (EditText) d.findViewById(R.id.etLoginPassword); String userName = etUserName.getText().toString().trim(); String password = etPassword.getText().toString().trim(); if (userName.isEmpty() || password.isEmpty()) { Toast.makeText(getApplicationContext(), "Please Fill all fields", Toast.LENGTH_SHORT).show(); builder.show();// here after validation message before retrun // it will reopen the dialog // till the user enter the right condition return; } user = Manager.get(getApplicationContext()).getUserByName(userName); if (user == null) { Toast.makeText(getApplicationContext(), "Error ethier username or password are wrong", Toast.LENGTH_SHORT).show(); builder.show(); return; } if (password.equals(user.getPassword())) { etPassword.setText(""); etUserName.setText(""); setLogged(1); setLoggedId(user.getUserId()); Toast.makeText(getApplicationContext(), "Successfully logged in", Toast.LENGTH_SHORT).show(); dialog.dismiss();// if every thing is ok then dismiss the dialog } else { Toast.makeText(getApplicationContext(), "Error ethier username or password are wrong", Toast.LENGTH_SHORT).show(); builder.show(); return; } } }); builder.show(); } 

Если вы используете material design я бы предложил проверить материалы-диалоги . Он исправил несколько проблем для меня, связанных с открытыми Android-ошибками (см. 78088 ), но, самое главное, для этого билета у него есть флаг autoDismiss который можно установить при использовании Builder .

Его можно было бы построить проще всего:

Диалог оповещений с пользовательским представлением и двумя кнопками (положительный и отрицательный).

 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()).setTitle(getString(R.string.select_period)); builder.setPositiveButton(getString(R.string.ok), null); builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // Click of Cancel Button } }); LayoutInflater li = LayoutInflater.from(getActivity()); View promptsView = li.inflate(R.layout.dialog_date_picker, null, false); builder.setView(promptsView); DatePicker startDatePicker = (DatePicker)promptsView.findViewById(R.id.startDatePicker); DatePicker endDatePicker = (DatePicker)promptsView.findViewById(R.id.endDatePicker); final AlertDialog alertDialog = builder.create(); alertDialog.show(); Button theButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); theButton.setOnClickListener(new CustomListener(alertDialog, startDatePicker, endDatePicker)); 

CustomClickLister of Positive Button of Alert Dailog :

 private class CustomListener implements View.OnClickListener { private final Dialog dialog; private DatePicker mStartDp, mEndDp; public CustomListener(Dialog dialog, DatePicker dS, DatePicker dE) { this.dialog = dialog; mStartDp = dS; mEndDp = dE; } @Override public void onClick(View v) { int day1 = mStartDp.getDayOfMonth(); int month1= mStartDp.getMonth(); int year1 = mStartDp.getYear(); Calendar cal1 = Calendar.getInstance(); cal1.set(Calendar.YEAR, year1); cal1.set(Calendar.MONTH, month1); cal1.set(Calendar.DAY_OF_MONTH, day1); int day2 = mEndDp.getDayOfMonth(); int month2= mEndDp.getMonth(); int year2 = mEndDp.getYear(); Calendar cal2 = Calendar.getInstance(); cal2.set(Calendar.YEAR, year2); cal2.set(Calendar.MONTH, month2); cal2.set(Calendar.DAY_OF_MONTH, day2); if(cal2.getTimeInMillis()>=cal1.getTimeInMillis()){ dialog.dismiss(); Log.i("Dialog", "Dismiss"); // Condition is satisfied so do dialog dismiss }else { Log.i("Dialog", "Do not Dismiss"); // Condition is not satisfied so do not dialog dismiss } } } 

Готово

My solution is simple, just use a custom layout for your DialogFragment and add a LinearLayout under your content which can be styled as borderless to match Google Material Design, then find the newly created Buttons and Override their OnClickListener: DialogFragment.java code:

  public class AddTopicFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); // Get the layout inflater LayoutInflater inflater = getActivity().getLayoutInflater(); final View dialogView = inflater.inflate(R.layout.dialog_add_topic, null); Button saveTopicDialogButton = (Button) dialogView.findViewById(R.id.saveTopicDialogButton); Button cancelSaveTopicDialogButton = (Button) dialogView.findViewById(R.id.cancelSaveTopicDialogButton); final AppCompatEditText addTopicNameET = (AppCompatEditText) dialogView.findViewById(R.id.addTopicNameET); final AppCompatEditText addTopicCreatedByET = (AppCompatEditText) dialogView.findViewById(R.id.addTopicCreatedByET); saveTopicDialogButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // validate inputs if(addTopicNameET.getText().toString().trim().isEmpty()){ addTopicNameET.setError("Topic name can't be empty"); addTopicNameET.requestFocus(); }else if(addTopicCreatedByET.getText().toString().trim().isEmpty()){ addTopicCreatedByET.setError("Topic created by can't be empty"); addTopicCreatedByET.requestFocus(); }else { // save topic to database Topic topic = new Topic(); topic.name = addTopicNameET.getText().toString().trim(); topic.createdBy = addTopicCreatedByET.getText().toString().trim(); topic.createdDate = new Date().getTime(); topic.save(); AddTopicFragment.this.dismiss(); } } }); cancelSaveTopicDialogButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AddTopicFragment.this.dismiss(); } }); // Inflate and set the layout for the dialog // Pass null as the parent view because its going in the dialog layout builder.setView(dialogView) .setMessage(getString(R.string.add_topic_message)); return builder.create(); } } 

dialog_add_topic.xml

  <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:padding="@dimen/activity_horizontal_margin" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" app:errorEnabled="true"> <android.support.v7.widget.AppCompatEditText android:id="@+id/addTopicNameET" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Topic Name" android:inputType="textPersonName" android:maxLines="1" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" app:errorEnabled="true"> <android.support.v7.widget.AppCompatEditText android:id="@+id/addTopicCreatedByET" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Created By" android:inputType="textPersonName" android:maxLines="1" /> </android.support.design.widget.TextInputLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:text="@string/cancel" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/cancelSaveTopicDialogButton" style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog" /> <Button android:text="@string/save" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/saveTopicDialogButton" style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog" /> </LinearLayout> </LinearLayout> 

This is the final result: