it-swarm.com.ru

Как закрыть диалоговое окно, нажав на него снаружи?

Я реализовал собственный диалог для своего приложения. Я хочу реализовать это, когда пользователь щелкает за пределами диалогового окна, диалоговое окно будет закрыто .. Что я должен сделать для этого?

137
iDroid Explorer

Вы можете использовать функцию dialog.setCanceledOnTouchOutside(true);, которая закроет диалоговое окно, если вы нажмете вне диалогового окна.

Что-то вроде,

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

Или если ваш диалог не в модели, то

1 - Установите флаг -FLAG_NOT_TOUCH_MODAL для атрибута окна вашего диалога

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

2 - Добавить еще один флаг в свойствах окон , FLAG_WATCH_OUTSIDE_TOUCH - этот диалог предназначен для получения события касания за пределами видимой области.

3 - Переопределить onTouchEvent() диалога и проверить тип действия. если тип действия - 'MotionEvent.ACTION_OUTSIDE 'означает, что пользователь взаимодействует вне области диалога. Таким образом, в этом случае вы можете уменьшить размер своего диалогового окна или решить, что вы хотите выполнить.

public boolean onTouchEvent(MotionEvent event)  
{  

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

Для получения дополнительной информации смотрите Как закрыть пользовательский диалог на основе точек касания? and Как отменить ваш немодальный диалог, если его коснуться за пределами области диалога

327
user370305

Вы можете использовать эту реализацию onTouchEvent. Это предотвращает реакцию под действием на событие касания (как упомянуто как).

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

Источник: http://blog.twimager.com/2010/08/closing-activity-by-touching-outside.html

16
Lukas Novak

Просто использовать 

dialog.setCanceledOnTouchOutside(true);
14
Ebin Sebastian

Или, если вы настраиваете диалог, используя тему, определенную в вашем стиле xml, поместите эту строку в вашу тему:

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

закрыть диалог на ощупь снаружи.

И если вы не хотите закрывать на ощупь снаружи, используйте код ниже:

dialog.setCanceledOnTouchOutside(false);
6
Naveen

Этот метод должен полностью избегать действий ниже серой области, извлекающих события щелчка.

Удалить эту строку, если она у вас есть:

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

Поместите это в свою деятельность, созданную

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

затем переопределить событие касания с этим

@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

Вы можете попробовать это: -

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

или же

alertDialog.setCancelable(true);

И если у вас есть AlterDialog.Builder, то вы можете попробовать это: -

alertDialogBuilder.setCancelable(true);
4
Mohammad Julfikar

Этот код используется для того, чтобы при щелчке по диалоговому окну использовать время скрытия входа в систему и когда пользователь щелкает по внешней стороне диалогового окна, когда время ввода и ввода софта совпадают.

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

Другое решение, этот код был вырезан из исходного кода Android Window Вам просто нужно добавить эти два метода в исходный код вашего диалога. 

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

Это решение не имеет этой проблемы: 

Это прекрасно работает, за исключением того, что действие под ним также реагирует на событие касания. Есть ли способ предотвратить это? - как

2
Lemberg

Вызовите dialog.setCancelable(false); из вашей деятельности/фрагмента.

0
EKN

Вы можете создать background, занимающий весь размер экрана transparent, и прослушать событие onClick для dismiss it.

0
oriolpons