Come chiudere la finestra di dialogo facendo clic all'esterno della finestra di dialogo?


Risposte:


356

È possibile utilizzare dialog.setCanceledOnTouchOutside(true);ciò che chiuderà la finestra di dialogo se si tocca al di fuori della finestra di dialogo.

Qualcosa di simile a,

  Dialog dialog = new Dialog(context)
  dialog.setCanceledOnTouchOutside(true);

O se la tua finestra di dialogo non è modello allora,

1 - Imposta il flag - FLAG_NOT_TOUCH_MODALper l'attributo della finestra della tua finestra di dialogo

Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);

2 - Aggiungi un altro flag alle proprietà di Windows, FLAG_WATCH_OUTSIDE_TOUCH- questo è per la finestra di dialogo per ricevere l'evento touch al di fuori della sua area visibile.

3 - Sostituisci la onTouchEvent()finestra di dialogo e controlla il tipo di azione. se il tipo di azione è ' MotionEvent.ACTION_OUTSIDE' significa che l'utente sta interagendo al di fuori dell'area di dialogo. Quindi, in questo caso, puoi ridimensionare la finestra di dialogo o decidere cosa vuoi eseguire. visualizzare il testo in chiaro?

public boolean onTouchEvent(MotionEvent event)  
{  

       if(event.getAction() == MotionEvent.ACTION_OUTSIDE){  
        System.out.println("TOuch outside the dialog ******************** ");  
               this.dismiss();  
       }  
       return false;  
}  

Per maggiori informazioni guarda Come chiudere una finestra di dialogo personalizzata basata su punti di contatto? e Come chiudere la finestra di dialogo non modale quando viene toccata al di fuori dell'area di dialogo


9
Funziona benissimo tranne che l'attività sottostante reagisce anche all'evento touch. C'è un modo per impedirlo?
howettl

Si. window.setFlags (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); causa questo problema. Ho pubblicato una soluzione di seguito :)
Unknownweirdo il

È possibile propagare eventi "on-touch-outside" all'attività sottostante usando anche una finestra di dialogo non personalizzata?
jc,

1
@howettl Ho risolto il tuo problema nella mia soluzione che ho pubblicato di seguito in cui non ho bisogno di impostare alcun flag su finestra.
Roman Nazarevych,

@MuhammedRefaat - Dai un'occhiata a questo thread groups.google.com/forum/#!topic/android-developers/VhaiIMl6E_w . Lo hanno ben descritto.
user370305,

18

Basta usare

dialog.setCanceledOnTouchOutside(true);

So che questa dovrebbe essere la risposta giusta, ma non funziona per me, e non so proprio perché.
IgniteCoders,

16

È possibile utilizzare questa implementazione di onTouchEvent. Impedisce di reagire al di sotto dell'attività all'evento touch (come detto howettl).

@Override
public boolean onTouchEvent ( MotionEvent event ) {
  // I only care if the event is an UP action
  if ( event.getAction () == MotionEvent.ACTION_UP ) {
    // create a rect for storing the window rect
    Rect r = new Rect ( 0, 0, 0, 0 );
    // retrieve the windows rect
    this.getWindow ().getDecorView ().getHitRect ( r );
    // check if the event position is inside the window rect
    boolean intersects = r.contains ( (int) event.getX (), (int) event.getY () );
    // if the event is not inside then we can close the activity
    if ( !intersects ) {
      // close the activity
      this.finish ();
      // notify that we consumed this event
      return true;
    }
  }
  // let the system handle the event
  return super.onTouchEvent ( event );
}

Fonte: http://blog.twimager.com/2010/08/closing-activity-by-touching-outside.html


9

Oppure, se stai personalizzando la finestra di dialogo usando un tema definito nel tuo stile xml, inserisci questa linea nel tuo tema:

<item name="android:windowCloseOnTouchOutside">true</item>

Questo non funziona per me su Samsung Galaxy Tab 2 WiFi. dialog.setCanceledOnTouchOutside(true);funziona meravigliosamente.
doplumi,

7
dialog.setCanceledOnTouchOutside(true); 

per chiudere la finestra di dialogo al tocco esterno.

E se non si desidera chiudere al tatto all'esterno, utilizzare il codice seguente:

dialog.setCanceledOnTouchOutside(false);

6

Questo metodo dovrebbe evitare completamente le attività al di sotto dell'area grigia che recupera eventi di clic.

Rimuovi questa linea se ce l'hai:

window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);

Metti questo sulla tua attività creata

getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);

quindi sovrascrivere l'evento touch con questo

@Override
public boolean onTouchEvent(MotionEvent ev)
{
    if(MotionEvent.ACTION_DOWN == ev.getAction())
    {
        Rect dialogBounds = new Rect();
        getWindow().getDecorView().getHitRect(dialogBounds);
        if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
            // You have clicked the grey area
            displayYourDialog();
            return false; // stop activity closing
        }
    }

    // Touch events inside are fine.
    return super.onTouchEvent(ev);
}

4

Puoi provare questo: -

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

o

alertDialog.setCancelable(true);

E se hai un AlterDialog.BuilderQuindi puoi provare questo: -

alertDialogBuilder.setCancelable(true);

4

Questo codice viene utilizzato per quando si fa clic sulla finestra di dialogo in quel momento nasconde l'inserimento e quando l'utente fa clic sul lato esterno della finestra in quel momento sia l'input software che la finestra di dialogo sono vicini.

dialog = new Dialog(act) {
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Tap anywhere to close dialog.
        Rect dialogBounds = new Rect();
        getWindow().getDecorView().getHitRect(dialogBounds);
        if (!dialogBounds.contains((int) event.getX(),
                (int) event.getY())) {
            // You have clicked the grey area
            InputMethodManager inputMethodManager = (InputMethodManager) act
                    .getSystemService(act.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(dialog
                    .getCurrentFocus().getWindowToken(), 0);
            dialog.dismiss();
            // stop activity closing
        } else {
            InputMethodManager inputMethodManager = (InputMethodManager) act
                    .getSystemService(act.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(dialog
                    .getCurrentFocus().getWindowToken(), 0);
        }

        return true;
    }
};

2

Un'altra soluzione, questo codice è stato preso dal codice sorgente Android di Window Devi solo aggiungere questi due metodi al codice sorgente della finestra di dialogo.

@Override
public boolean onTouchEvent(MotionEvent event) {        
    if (isShowing() && (event.getAction() == MotionEvent.ACTION_DOWN
            && isOutOfBounds(getContext(), event) && getWindow().peekDecorView() != null)) {
        hide();
    }
    return false;
}

private boolean isOutOfBounds(Context context, MotionEvent event) {
    final int x = (int) event.getX();
    final int y = (int) event.getY();
    final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
    final View decorView = getWindow().getDecorView();
    return (x < -slop) || (y < -slop)
            || (x > (decorView.getWidth()+slop))
            || (y > (decorView.getHeight()+slop));
}

Questa soluzione non presenta questo problema:

Funziona benissimo tranne che l'attività sottostante reagisce anche all'evento touch. C'è un modo per impedirlo? - howettl


Non puoi semplicemente rendere modale la tua finestra di dialogo se non vuoi che altri Windows ricevano eventi?

1

Chiama dialog.setCancelable(false);dalla tua attività / frammento.



0

Puoi backgroundoccupare tutte le dimensioni dello schermotransparent e ascoltare l' onClickevento dismiss.


10
Risposta pessima! Naturalmente questo può essere fatto, ma per favore fallo nel modo giusto!
jc,

-1

Ecco il codice

    dialog.getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent ev) {

            if(MotionEvent.ACTION_DOWN == ev.getAction())
            {
                Rect dialogBounds = new Rect();
                dialog. getWindow().getDecorView().getHitRect(dialogBounds);
                if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
                    // You have clicked the grey area
                    UiUtils.hideKeyboard2(getActivity());
                    return false; // stop activity closing
                }
            }
            getActivity().dispatchTouchEvent(ev);
            return false;
        }
    });

Prova questo . puoi nascondere la tastiera quando tocchi fuori

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.