¿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


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

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


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>

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

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

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

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

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


¿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.



0

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


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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.