Не допускайте закриття діалогового вікна 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.