Я применил специальный диалог для своего приложения. Я хочу реализовать это, когда пользователь щелкает за пределами диалогового окна, диалог будет отклонен. Что мне нужно сделать для этого?
Как отклонить диалог, нажав на него вне диалога?
Ответ 1
Вы можете использовать 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;  
}  
Подробнее о Как отклонить пользовательский диалог, основанный на точках касания? и Как отклонить ваш немодальный диалог при касании внешней области диалога
Ответ 2
Вы можете использовать эту реализацию 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
Ответ 3
Просто используйте
dialog.setCanceledOnTouchOutside(true);
		Ответ 4
Или, если вы настраиваете диалог, используя тему, определенную в вашем стиле xml, поместите эту строку в свою тему:
<item name="android:windowCloseOnTouchOutside">true</item>
		Ответ 5
dialog.setCanceledOnTouchOutside(истина);
закрыть диалог при касании снаружи
и если вы не хотите закрываться при касании снаружи, используйте ниже
dialog.setCanceledOnTouchOutside(ложь);
Ответ 6
Этот метод должен полностью избегать действий ниже серых областей, получающих события щелчка.
Удалите эту строку, если она у вас есть:
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);
}
		Ответ 7
Другое решение, которое этот код был отрезан от исходного кода 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));
}
Это решение не имеет этой проблемы:
Это отлично работает, за исключением того, что активность под ним также реагирует на событие touch. Есть ли способ предотвратить это? - howettl
Ответ 8
Вы можете попробовать следующее: -
AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);
или
alertDialog.setCancelable(true);
И если у вас есть AlterDialog.Builder Тогда вы можете попробовать следующее: -
alertDialogBuilder.setCancelable(true);
		Ответ 9
Этот код используется для использования при щелчке по диалоговому окну, которое время hidesoftinput и когда пользователь нажимает на внешнюю сторону диалогового окна, что время как softinput, так и диалоговое окно близко...
 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;
                        }
                    };
		Ответ 10
Вы можете сделать background занимая весь размер экрана transparent и прослушать событие onClick до dismiss it.
Ответ 11
вызов dialog.setCancelable(false); из вашей активности/фрагмента