¿Cómo descartar el cuadro de diálogo haciendo clic fuera del cuadro de diálogo?

Respuestas:

356

Puede usar dialog.setCanceledOnTouchOutside(true);cual cerrará el cuadro de diálogo si toca fuera del cuadro de diálogo.

Algo como,

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

O si su cuadro de diálogo no es modelo, entonces,

1 - Establezca la bandera FLAG_NOT_TOUCH_MODALpara el atributo de ventana de diálogo

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

2 - Agregue otra bandera a las propiedades de Windows, FLAG_WATCH_OUTSIDE_TOUCH- esta es para que el diálogo reciba un evento táctil fuera de su región visible.

3 - Anular el onTouchEvent()diálogo y verificar el tipo de acción. si el tipo de acción es ' MotionEvent.ACTION_OUTSIDE' significa, el usuario está interactuando fuera de la región de diálogo. Entonces, en este caso, puede oscurecer su diálogo o decidir qué desea realizar. ver plano?

public boolean onTouchEvent(MotionEvent event)  
{  

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

Para obtener más información, consulte ¿Cómo descartar un cuadro de diálogo personalizado basado en puntos de contacto? y Cómo descartar su diálogo no modal, cuando se toca fuera de la región del diálogo

usuario370305
fuente
9
Esto funciona muy bien, excepto que la actividad debajo también reacciona al evento táctil. ¿Hay alguna forma de prevenir esto?
howettl
Si. window.setFlags (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); causa este problema He publicado una solución a continuación :)
Unknownweirdo
¿Es posible propagar eventos 'on-touch-outside' a la actividad debajo usando un diálogo no personalizado también?
jc
1
@howettl He resuelto su problema en mi solución que he publicado a continuación, donde no necesito establecer ningún indicador en la ventana.
Roman Nazarevych
@ MuhammedRefaat: mira este hilo groups.google.com/forum/#!topic/android-developers/VhaiIMl6E_w . Lo describieron muy bien.
user370305
18

Simplemente use

dialog.setCanceledOnTouchOutside(true);
Ebin Sebastian
fuente
Sé que esta debería ser la respuesta correcta, pero no funciona para mí, y simplemente no sé por qué.
IgniteCoders
16

Puede usar esta implementación de onTouchEvent. Impide reaccionar debajo de la actividad al evento táctil (como se mencionó 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 );
}

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

Lukas Novak
fuente
9

O, si está personalizando el cuadro de diálogo utilizando un tema definido en su estilo xml, ponga esta línea en su tema:

<item name="android:windowCloseOnTouchOutside">true</item>
Chris.Zou
fuente
Esto no funciona para mí en Samsung Galaxy Tab 2 WiFi. dialog.setCanceledOnTouchOutside(true);funciona maravillosamente
doplumi
7
dialog.setCanceledOnTouchOutside(true); 

para cerrar el diálogo al tocar afuera.

Y si no desea cerrar al tacto, use el siguiente código:

dialog.setCanceledOnTouchOutside(false);
Naveen
fuente
6

Este método debería evitar por completo las actividades debajo del área gris recuperando eventos de clic.

Elimine esta línea si la tiene:

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

Pon esto en tu actividad creada

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

luego anule el evento táctil con esto

@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);
}
Extraño desconocido
fuente
4

Puedes probar esto: -

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

o

alertDialog.setCancelable(true);

Y si tienes un AlterDialog.BuilderEntonces puedes probar esto: -

alertDialogBuilder.setCancelable(true);
Julfikar
fuente
4

Este código se usa para cuando se hace clic en el cuadro de diálogo que oculta el tiempo de entrada y cuando el usuario hace clic en el lado exterior del cuadro de diálogo ese tiempo, tanto el softinput como el cuadro de diálogo están cerrados.

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;
    }
};
Maulik Santoki
fuente
2

Otra solución, este código fue tomado del código fuente de Android Window . Debe agregar estos dos métodos al código fuente de su diálogo.

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

Esta solución no tiene este problema:

Esto funciona muy bien, excepto que la actividad debajo también reacciona al evento táctil. ¿Hay alguna forma de prevenir esto? - howettl

Roman Nazarevych
fuente
¿No puede hacer que su diálogo toque modal si no desea que otras ventanas reciban eventos?
1

Llama dialog.setCancelable(false);desde tu actividad / fragmento.

EKN
fuente
1

Lo siguiente me ha funcionado:

myDialog.setCanceledOnTouchOutside(true);
Akanshi Srivastava
fuente
0

Puede hacer que backgroundocupe todo el tamaño de la pantalla transparenty escuchar el onClickevento dismiss.

oriolpons
fuente
10
Muy mala respuesta! Por supuesto, esto se puede hacer, ¡pero hágalo de la manera correcta!
jc
-1

Aqui esta el codigo

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

Prueba este. puedes ocultar el teclado cuando tocas afuera

Saljith Kj
fuente