Предотвращение закрытия диалогового окна активности Android при внешнем прикосновении


229

У меня есть действие, которое использует стиль Theme.Dialog, так что это плавающее окно поверх другого действия. Однако когда я щелкаю за пределами диалогового окна (в фоновом режиме), диалоговое окно закрывается. Как я могу остановить это поведение?


1
Зачем ты это делаешь? Если нужное вам поведение - это диалог, почему бы не использовать диалог? Что касается вашего вопроса, я не думаю, что есть решение для этого.
Кумар Бибек

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

1
И OP хочет модальное диалоговое окно, то есть диалоговое окно, которое вынуждает пользователя отвечать, например, OK или Да / Нет. Пользователь не должен иметь возможность просто щелкнуть мышью.
Скотт Биггс

Ответы:


34

Это может помочь вам. Это способ обработки внешнего события касания:

Как отменить диалоговое окно, например «Активность», при касании за пределами окна?

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

(PS: код использует WindowManager.LayoutParams)


1
Однако объект не является диалогом, это действие, которое использует стиль диалога. Активность не имеет этого метода и не может быть приведена к диалогу.
Fergusmac

Ваш пост - полная противоположность тому, что спросили. он спросил, как предотвратить закрытие, а не как его вызвать.
ChuckKelly

4
Вот что он объяснил словами: «Улавливая событие и ничего не делая, я думаю, что вы можете предотвратить закрытие».
Метр

4
по какой-то причине после выполнения всего FLAG_NOT_MODAL, WATCH_OUTSIDE_TOUCH, внешнее касание фактически не закрывает действия, а нажимается кнопка позади действия. есть идеи для этого?
njzk2

Обратите внимание, что у диалогов есть тень (по крайней мере, до сих пор (8.0)): если вы нажмете на тень, Android будет интерпретировать этот щелчок точно так же, как это было внутри диалога. Просто хотел поделиться этим с миром, мне потребовалось 10 минут, чтобы получить это.
Лоренцо фон Маттерхорн

459

Чтобы предотвратить закрытие диалогового окна при нажатии клавиши «Назад», используйте эту

dialog.setCancelable(false);

И чтобы диалоговое окно не закрывалось от внешнего прикосновения, используйте это

 dialog.setCanceledOnTouchOutside(false);

4
Этот ответ полезен, но этот вопрос касается активности с использованием атрибута Theme.Dialog.
Пареш Майани

15
Я знаю, когда осознаю, что уже слишком поздно, поскольку это помогло многим людям, поэтому не удалило его.
Сингхак,

12
Я знаю, что это на самом деле не относится к вопросу, но это помогло мне. Спасибо!
Деннисдрю

5
Это лучший ответ. Я подозреваю, что большинство людей, которые находят этот вопрос, ищут способ не допустить AlertDialogзакрытия стандарта на ощупь снаружи, и это то, что дает этот ответ.
aroth

20
На более новых версиях AlertDialog вам нужно только использоватьsetCancelable(false)
Kobi Tate

120

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

РЕДАКТИРОВАТЬ: Это работает только с Android API уровня 11 или выше


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

Это не мешает кнопке «назад» в этом диалоге Activity без onBackPressed (). Прекрасно работает с this.setFinishOnTouchOutside (false).
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

Достаточно установить для диалогового окна отменяемое значение false, и если вы дотронетесь до диалогового окна предупреждения или нажмете кнопку «Назад», диалоговое окно предупреждения исчезнет. Так что используйте это:

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

запретить пользователю нажимать за пределами диалогового окна.


7

Alert Dialog устарела, поэтому используйте Dialog dialog = new Dialog (this);

Для предотвращения близкого при внешнем прикосновении

dialog.setCanceledOnTouchOutside(false);

5

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


5

Я использую это в onCreate (), кажется, работает на любой версии Android; протестирован на 5.0 и 4.4.x, не может тестироваться на Gingerbread, на устройствах Samsung (Note 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в диалоге и ничего не делать внутри. Но Диалог уволить при повороте экрана тоже. Чтобы исправить это, я установил переменную, чтобы сказать мне, если диалог обычно закрывается. Затем я устанавливаю OnDismissListenerсвой диалог и внутри проверяю переменную. Если диалог обычно исчезает, я ничего не делаю, или я снова запускаю диалог (и устанавливаю его состояние, как при отклонении в моем случае).


1

builder.setCancelable (ложь);


public void Mensaje (View 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.