Zapobiegaj zamykaniu okna dialogowego aktywności Androida po dotknięciu z zewnątrz


228

Mam działanie, które korzysta ze stylu Theme.Dialog, dzięki czemu jest to ruchome okno nad innym działaniem. Jednak gdy kliknę poza oknem dialogowym (w tle), okno dialogowe zostanie zamknięte. Jak mogę zatrzymać to zachowanie?


1
Dlaczego miałbyś to zrobić? JEŚLI pożądane zachowanie dotyczy dialogu, dlaczego nie skorzystać z okna dialogowego? Jeśli chodzi o twoje pytanie, nie sądzę, że istnieje na to rozwiązanie.
Kumar Bibek

Dialogi @KumarBibek są ograniczone, jeśli chodzi o dostosowanie układu ... dlatego aktywność. Nawet dokumentacja dla programistów zaleca to podejście w celu elastycznego dostosowania
Leo

1
Tym, czego chce OP, jest okno modalne , tj. Okno dialogowe, które zmusza użytkownika do odpowiedzi, takie jak OK lub Tak / Nie. Użytkownik nie powinien być w stanie po prostu kliknąć.
Scott Biggs,

Odpowiedzi:


33

To może ci pomóc. Jest to sposób na obsługę dotyku zdarzenia zewnętrznego:

Jak anulować okno dialogowe takie jak Aktywność po dotknięciu za oknem?

Chwytając zdarzenie i nie robiąc nic, myślę, że możesz zapobiec zamknięciu. Dziwne jest jednak to, że domyślnym zachowaniem okna dialogowego aktywności nie powinno być zamykanie się po dotknięciu na zewnątrz.

(PS: kod używa WindowManager.LayoutParams)


1
Obiekt nie jest oknem dialogowym, jest to działanie wykorzystujące styl okna dialogowego. Aktywność nie ma tej metody i nie można jej przesyłać do okna dialogowego.
Fergusmac

Twój post jest dokładnym przeciwieństwem pytania. zapytał, jak zapobiegać zamykaniu, a nie jak je powodować.
ChuckKelly,

4
Właśnie to wyjaśnił w „Łapiąc to wydarzenie i nic nie robiąc, myślę, że możesz zapobiec zamknięciu”.
metter

4
z jakiegoś powodu, po zrobieniu całego FLAG_NOT_MODAL, WATCH_OUTSIDE_TOUCH, dotyk zewnętrzny tak naprawdę nie zamyka działań, ale kliknięty jest przycisk stojący za działaniem. jakiś pomysł na to?
njzk2,

Pamiętaj, że okna dialogowe mają cień (przynajmniej do tej pory (8.0)): jeśli klikniesz cień, Android zinterpretuje to kliknięcie tak, jak w oknie dialogowym. Chciałem tylko podzielić się tym ze światem, zajęło mi to 10 minut.
Lorenzo Von Matterhorn

458

Aby zapobiec odrzuceniu okna dialogowego po naciśnięciu klawisza Wstecz, użyj tego

dialog.setCancelable(false);

Aby uniknąć odrzucenia okna dialogowego przy użyciu dotyku zewnętrznego, użyj tego

 dialog.setCanceledOnTouchOutside(false);

4
Ta odpowiedź jest pomocna, ale pytanie dotyczy aktywności za pomocą atrybutu Theme.Dialog.
Paresh Mayani

15
Wiem, kiedy zdaję sobie sprawę, że jest już za późno, ponieważ pomaga wielu osobom, więc go nie usunąłem.
Singhak

12
Wiem, że to tak naprawdę nie dotyczyło pytania, ale pomogło mi to. Dzięki!
dennisdrew

5
To najlepsza odpowiedź. Podejrzewam, że większość osób, które znajdą to pytanie, szuka sposobu, aby zapobiec AlertDialogzamknięciu standardu za pomocą dotyku na zewnątrz, i to właśnie zapewnia ta odpowiedź.
aroth

20
W nowszych wersjach AlertDialog wystarczy użyćsetCancelable(false)
Kobi Tate

120

To, co faktycznie masz, to Działanie (nawet jeśli wygląda jak okno dialogowe), dlatego powinieneś zadzwonić setFinishOnTouchOutside(false)z tego działania, jeśli chcesz, aby było otwarte po kliknięciu działania w tle.

EDYCJA: Działa to tylko z Androidem API poziomu 11 lub wyższym


4
Nie uniemożliwia to naciśnięcia przycisku „wstecz” w swojej aktywności. Musisz więc również pominąć onBackPressed()robienie niczego w jego ciele
Alex Bonel,

Nie zapobiega przyciskowi „wstecz” w tym oknie dialogowym Działanie bez funkcji onBackPressed (). Działa idealnie z this.setFinishOnTouchOutside (false).
Kunalxigxag

68

To, co zadziałało, to stworzenie DialogFragmentzestawu, którego nie można anulować:

dialog.setCancelable(false);

1
Niepomocne. To pytanie dotyczy działań, a nie dialogów.
Scott Biggs,

20

Gdy używasz okna dialogowego jako działania w onCreate, dodaj to

setFinishOnTouchOutside(false);

17

W przypadku wyższego interfejsu API 10 okno dialogowe znika po dotknięciu na zewnątrz, natomiast w interfejsie niższym niż API 11 okno dialogowe nie znika. Aby temu zapobiec, musisz:

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

LUB

W onCreate()metodzie użyj:this.setFinishOnTouchOutside(false);

Uwaga: w przypadku API 10 i niższych ta metoda nie działa i nie jest potrzebna.


14

Wystarczy ustawić wartość parametru cancelable na false, a albo dotkniesz okna dialogowego alertu, albo klikniesz przycisk Wstecz, zniknie okno alertu. Więc użyj tego:

setCancelable(false)

A druga funkcja nie jest już konieczna: dialog.setCanceledOnTouchOutside(false);

Jeśli tworzysz tymczasowe okno dialogowe i zastanawiasz się nad umieszczeniem tego wiersza kodu, oto przykład:

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

Użyj tego kodu, to działa dla mnie

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


to powinna być poprawna odpowiedź, jeśli mógłby zrobić prawidłowe pytanie!
alijunior

2
To byłaby poprawna odpowiedź, gdyby PO pytał o dialogi ! Ale pytanie dotyczy działań - zupełnie innego przypadku.
Scott Biggs,

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.

Obejrzyj ten link, aby uzyskać więcej informacji na temat okna dialogowego.

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

Pamiętaj, że pytanie dotyczy działań używanych jako okna dialogowe, NIE klasy Dialog.
Scott Biggs,

8

Po prostu,

alertDialog.setCancelable(false);

uniemożliwić użytkownikowi kliknięcie poza oknem dialogowym.


6

Alert Dialog jest przestarzały, więc użyj Dialog dialog = new Dialog (this);

Aby zapobiec zbliżeniu na dotyk zewnętrzny

dialog.setCanceledOnTouchOutside(false);

5

Użyj setFinishOnTouchOutside(false)dla API> 11 i nie martw się, ponieważ domyślne zachowanie Androida, że ​​okno dialogowe o tematyce aktywności nie zostanie ukończone na zewnętrznym interfejsie dla API <11 :) !! Pozdrawiam !!


5

Używam tego w onCreate (), wydaje się działać na dowolnej wersji Androida; testowane na 5.0 i 4.4.x, nie można testować na Gingerbread, urządzenia Samsung (Uwaga 1 z GB) domyślnie mają to w ten sposób:

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

Myślę, że to ci pomoże. To zadziałało dla mnie


1
Spróbuj także wyjaśnić, dlaczego to zadziała ... Tylko zrzut kodu nie jest dobrą odpowiedzią.
Codebender

3

Oto moje rozwiązanie:

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

2

Możliwe jest także przypisanie różnych akcji implementujących onCancelListener:

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

Jak mogę sprawdzić, czy anulowanie jest wywoływane z powodu stuknięcia poza oknem dialogowym alertu?
cegprakash

Bardzo pomocne w tworzeniu niestandardowych akcji po stuknięciu poza oknem dialogowym alertu!
Adam S.

1

Miałem ten sam problem. Aby sobie z tym poradzić, ustawiam OntouchListenerw oknie dialogowym i nic nie robię w środku. Ale okno dialogowe odrzuca się również podczas obracania ekranu. Aby to naprawić, ustawiam zmienną, która informuje mnie, czy okno dialogowe zwykle zostało zamknięte. Następnie ustawiam a OnDismissListenerw oknie dialogowym i sprawdzam zmienną. Jeśli okno dialogowe nie działa normalnie, nic nie robię, bo inaczej uruchamiam je ponownie (i w moim przypadku ustawiam jego stan jak w przypadku zwolnienia).


1

builder.setCancelable (false);


public void Mensaje (Zobacz 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
Cześć Aleks. Witamy w StackOverflow i dziękuję za odpowiedź. Czy możesz edytować swoją odpowiedź, aby opisać, co robi Twój kod i jak to rozwiązuje problem PO? Odpowiedzi tylko na kod są odradzane, ponieważ nie uczą ani nie wyjaśniają, dlaczego . Dziękuję Ci!
Tim Malone,

-1

To idealna odpowiedź na wszystkie pytania .... Mam nadzieję, że lubisz kodować w Androidzie

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

Dziękujemy za ten fragment kodu, który może zapewnić ograniczoną, natychmiastową pomoc. Właściwe wyjaśnienie znacznie poprawiłoby jego długoterminową wartość, pokazując, dlaczego jest to dobre rozwiązanie problemu i uczyniłoby to bardziej użytecznym dla przyszłych czytelników z innymi podobnymi pytaniami. Edytuj swoją odpowiedź, aby dodać wyjaśnienie, w tym przyjęte założenia.
Maximilian Peters
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.