ti-enxame.com

Como descartar a caixa de diálogo com um clique fora da caixa de diálogo?

Eu implementei um diálogo personalizado para o meu aplicativo. Eu quero implementar isso quando o usuário clicar fora da caixa de diálogo, a caixa de diálogo será descartada. O que eu tenho que fazer para isso?

137
iDroid Explorer

Você pode usar dialog.setCanceledOnTouchOutside(true);, que fechará a caixa de diálogo se você tocar fora da caixa de diálogo.

Algo como,

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

Ou se o seu Dialog não for modelo então,

1 - Defina a flag -FLAG_NOT_TOUCH_MODAL para o atributo window do seu diálogo

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

2 - Adicione outro sinalizador às propriedades do Windows, FLAG_WATCH_OUTSIDE_TOUCH - este é para o diálogo receber um evento de toque fora de sua região visível.

3 - Substitua onTouchEvent() da caixa de diálogo e verifique o tipo de ação. se o tipo de ação for 'MotionEvent.ACTION_OUTSIDE' significa que o usuário está interagindo fora da região do diálogo. Portanto, neste caso, você pode escurecer sua caixa de diálogo ou decidir o que deseja executar. Exibir a impressão simples?

public boolean onTouchEvent(MotionEvent event)  
{  

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

Para mais informações, consulte Como descartar uma caixa de diálogo personalizada com base em pontos de contato? e Como descartar sua caixa de diálogo não-modal, quando tocada fora da região de diálogo

327
user370305

Você pode usar essa implementação do onTouchEvent. Impede de reagir abaixo da atividade ao evento do toque (como mencionado no 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

16
Lukas Novak

Simplesmente use 

dialog.setCanceledOnTouchOutside(true);
14
Ebin Sebastian

Ou, se você estiver personalizando a caixa de diálogo usando um tema definido em seu estilo xml, coloque esta linha em seu tema:

<item name="Android:windowCloseOnTouchOutside">true</item>
9
Chris.Zou
dialog.setCanceledOnTouchOutside(true); 

para fechar a caixa de diálogo ao tocar fora.

E se você não quiser fechar o contato do lado de fora, use o código abaixo:

dialog.setCanceledOnTouchOutside(false);
6
Naveen

Esse método deve evitar completamente atividades abaixo da área cinza recuperando eventos de clique.

Remover esta linha se você tiver:

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

Coloque isso na sua atividade criada

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

em seguida, substituir o evento de toque com este

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

Você pode tentar isso:

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

ou

alertDialog.setCancelable(true);

E se você tiver um AlterDialog.Builder Então você pode tentar isto: -

alertDialogBuilder.setCancelable(true);
4
Mohammad Julfikar

Este código é usado para quando o uso clica na caixa de diálogo que o tempo hidesoftinput e quando o usuário clica no lado externo da caixa de diálogo que o tempo softinput e caixa de diálogo estão fechadas.

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
Maulik Santoki

Outra solução este código foi cortado do código-fonte Android de Window Você deve apenas adicionar este dois métodos para o código-fonte do 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 solução não tem esse problema: 

Isso funciona muito bem, exceto que a atividade abaixo também reage ao evento de toque. Existe alguma maneira de evitar isso? - howettl

2
Lemberg

Chame dialog.setCancelable(false); da sua atividade/fragmento.

0
EKN

Você pode fazer um background ocupando todo o tamanho da tela transparent e ouvir o evento onClick para dismiss ele.

0
oriolpons