Не допускайте закриття діалогового вікна Android на зовнішньому дотику


228

У мене є діяльність, яка використовує стиль Theme.Dialog таким чином, що це плаваюче вікно над іншою діяльністю. Однак, коли я клацну за межами діалогового вікна (на фоновій активності), діалогове вікно закриється. Як я можу припинити таку поведінку?


1
Чому б ти це зробив? Якщо поведінка, яку ви хочете, має діалог, чому б не використовувати діалог? Що стосується вашого питання, я не думаю, що для цього немає рішення.
Кумар Бібек

Діалоги @KumarBibek обмежені, коли мова йде про налаштування макета ... ось чому діяльність. Навіть розробники документів рекомендують цей підхід для гнучкої настройки
Лев

1
І те, що OP хоче - це діалогове вікно Modal , тобто діалог, який змушує користувача реагувати, наприклад, OK або Так / Ні. Користувач не повинен мати можливість просто клацнути.
Скотт Біггс

Відповіді:


33

Це може вам допомогти. Це спосіб впоратися із зовнішньою подією:

Як скасувати діалоговий діалог, як-от "Діяльність", якщо торкнутися його за межами вікна

Захоплюючи подію і нічого не роблячи, я думаю, ви можете запобігти закриттю. Але що дивно, це те, що поведінка за умовчанням у вашому діалоговому вікні діяльності не повинна закриватися, коли ви торкаєтесь зовні.

(PS: у коді використовується WindowManager.LayoutParams)


1
Об'єкт не є діалогом, це діяльність, яка використовує стиль діалогу. Діяльність не має цього методу і не може бути передана до діалогового вікна.
Фергюсмак

ур-пост - це точно протилежне тому, що просили. він запитав, як запобігти закриттю, як не викликати.
ChuckKelly

4
Саме цим він пояснив "Зловивши подію і нічого не зробивши, я думаю, ви можете запобігти закриттю".
зустр

4
чомусь, виконавши весь FLAG_NOT_MODAL, WATCH_OUTSIDE_TOUCH, зовнішнє торкання дійсно не закриває дії, але натискається кнопка позаду діяльності. якась ідея для цього?
njzk2

Зауважте, що діалоги мають тінь (принаймні, до цих пір (8.0)): якщо ви натиснете на тінь, Android буде інтерпретувати цей клік так, як це було всередині діалогового вікна. Просто хотів поділитися цим світом, мені знадобилося 10 хвилин.
Лоренцо Фон Маттерхорн

458

Щоб запобігти відхиленню діалогового вікна після натискання на задній клавіші, використовуйте це

dialog.setCancelable(false);

І щоб не допустити звільнення діалогового вікна від зовнішнього дотику, використовуйте це

 dialog.setCanceledOnTouchOutside(false);

4
Ця відповідь корисна, але це питання стосується активності за допомогою атрибута Theme.Dialog.
Paresh Mayani

15
Я знаю, коли я усвідомлюю, що це занадто пізно, оскільки він допомагає багатьом людям, тому не видалив його.
Сінгак

12
Я знаю, що це насправді не стосувалося питання, але це допомогло мені. Дякую!
dennisdrew

5
Це найкраща відповідь. Я підозрюю, що більшість людей, які знайшли це питання, шукають спосіб запобігти AlertDialogзакриттю стандарту зовні, і саме це дає ця відповідь.
aroth

20
У більш нових версіях AlertDialog, вам потрібно всього лише використовуватиsetCancelable(false)
Кобі Tate

120

Насправді у вас є активність (навіть якщо вона схожа на діалог), тому вам слід зателефонувати setFinishOnTouchOutside(false)зі своєї діяльності, якщо ви хочете залишати її відкритою, коли натискаєте фонову активність.

EDIT: Це працює лише з андроїд API рівня 11 або вище


4
Це не заважає натискати кнопку "назад" у вашій діяльності. Тож вам також потрібно перекрити, onBackPressed()нічого не роблячи,
Алекс Бонел

У цьому діалоговому вікні Діяльність без onBackPress () це не перешкоджає кнопці "назад". Працює ідеально з цим.setFinishOnTouchOutside (помилково).
Kunalxigxag

68

Що для мене працювало, це створити DialogFragmentнабір, щоб його не можна було скасувати:

dialog.setCancelable(false);

1
Не корисно. Це питання стосується діяльності, а не діалогів.
Скотт Біггс

20

Якщо ви використовуєте діалог як діяльність у onCreate, додайте це

setFinishOnTouchOutside(false);

17

Що стосується більш високого API 10, діалог зникає, коли він торкається зовні, тоді як у нижчого за API 11 діалог не зникає. Щоб цього не допустити, потрібно зробити:

В styles.xml:<item name="android:windowCloseOnTouchOutside">false</item>

АБО

У onCreate()методі використовуйте:this.setFinishOnTouchOutside(false);

Примітка. Для API 10 та новіших версій цей метод не дає ефекту і не потрібен.


14

Достатньо встановити помилкове діалогове вікно, і якщо ви торкнетеся поза діалогового вікна сповіщення або натисніть кнопку "назад", діалог попередження зникне. Тому використовуйте цей:

setCancelable(false)

А інша функція більше не потрібна: dialog.setCanceledOnTouchOutside(false);

Якщо ви створюєте тимчасове діалогове вікно, і вам цікаво ввести цей рядок коду, ось такий приклад:

new AlertDialog.Builder(this)
                        .setTitle("Trial Version")
                        .setCancelable(false)
                        .setMessage("You are using trial version!")
                        .setIcon(R.drawable.time_left)
                        .setPositiveButton(android.R.string.yes, null).show();

12

Використовуйте цей код, він працює для мене

 AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
 alertDialog.setCancelable(false);


це має бути правильна відповідь, якщо він міг би поставити правильне запитання!
alijunior

2
Це була б правильна відповідь, якби ОП запитувала про діалоги ! Але питання про Діяльність - зовсім інший випадок.
Скотт Біггс

11
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true); 
//use this to dismiss the dialog on outside click of dialog

dialog.setCanceledOnTouchOutside(false);
//use this for not to dismiss the dialog on outside click of dialog.

Перегляньте це посилання, щоб отримати докладнішу інформацію про діалогове вікно.

dialog.setCancelable(false);
//used to prevent the dismiss of dialog on backpress of that activity

dialog.setCancelable(true);
//used to dismiss the dialog on onbackpressed of that activity

Зауважте, що це питання стосується Діянь, які використовуються як діалоги, а не класу Діалог.
Скотт Біггс

8

Просто,

alertDialog.setCancelable(false);

не дозволяти користувачеві клацати за межами діалогового вікна.


6

Діалог сповіщення застарілий, тому використовуйте діалогове вікно діалогу = новий діалог (це);

Для запобігання закриття від зовнішнього дотику

dialog.setCanceledOnTouchOutside(false);

5

Використовуйте setFinishOnTouchOutside(false)для API> 11, і не хвилюйтесь, оскільки його діалогове вікно Android за типовим діалоговим вікном тематики діяльності не закінчиться зовнішнім дотиком для API <11 :) !! Cheerss !!


5

Я використовую це в onCreate (), здається, працює на будь-якій версії Android; тестовано на 5.0 та 4.4.x, не вдається протестувати на Gingerbread, пристроях Samsung (Примітка 1, що працює на ГБ), це за замовчуванням:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
    {
        setFinishOnTouchOutside(false);
    }
    else
    {
        getWindow().clearFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
    }

    super.onCreate(savedInstanceState);

4
        alert.setCancelable(false);
        alert.setCanceledOnTouchOutside(false);

Я думаю, це допоможе тобі. Це працювало для мене


1
Будь ласка, спробуйте пояснити, чому це буде працювати ... Просто скидання коду не є гарною відповіддю.
Codebender

3

Ось моє рішення:

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select The Difficulty Level");
builder.setCancelable(false);

2

Також можна призначити різні дії, що реалізують onCancelListener:

alertDialog.setOnCancelListener(new DialogInterface.OnCancelListener(){                   
    @Override
    public void onCancel(DialogInterface dialogInterface) {
        //Your custom logic
    } 
});

Як я можу визначити, чи скасовується скасування через натискання поза діалоговим вікном сповіщення?
cegprakash

Дуже корисно створити спеціальні дії щодо натискання поза діалоговим вікном сповіщення!
Адам С.

1

Я зіткнувся з тією ж проблемою. Для цього я встановлюю OntouchListenerдіалогове вікно і нічого не роблю всередині. Але діалог відхиляється і при обертанні екрана. Щоб виправити це, я встановив змінну, щоб сказати мені, чи нормально діалогове вікно закрито. Потім я встановлюю a OnDismissListenerу свій діалог і всередині перевіряю змінну. Якщо діалогове вікно нормально відхиляється, я нічого не роблю, інакше я запускаю діалог ще раз (і встановлюю його стан як при відхиленні в моєму випадку).


1

builder.setCancelable (помилково);


публічна недійсність Mensaje (Переглянути v) {

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("¿Quieres ir a el Menú principal?");
    builder.setMessage("Al presionar SI iras a el menú y saldras de la materia.");
    builder.setPositiveButton("SI", null);
    builder.setNegativeButton("NO", null);
    builder.setCancelable(false);
    builder.show();
}

1
Привіт Алекс. Ласкаво просимо до StackOverflow і дякуємо за вашу відповідь. Чи можете ви відредагувати свою відповідь, щоб описати, що робить ваш код, і як це вирішує проблему ОП? Відповіді на код лише відмовляються, оскільки вони не навчають і не пояснюють, чому . Дякую!
Тім Малоун

-1

Це ідеальна відповідь на всі ваші запитання .... Сподіваюся, вам сподобається кодування в Android

new AlertDialog.Builder(this)
            .setTitle("Akshat Rastogi Is Great")
            .setCancelable(false)
            .setMessage("I am the best Android Programmer")
            .setPositiveButton("I agree", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();

                }
            })
            .create().show();

Дякуємо за цей фрагмент коду, який може надати деяку обмежену, негайну допомогу. Правильне пояснення значно покращило б його довгострокове значення, показавши, чому це хороше рішення проблеми та зробило б кориснішим майбутнім читачам інші подібні питання. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення, включаючи зроблені вами припущення.
Максиміліан Пітерс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.