关于给Dialog设置setCanceledOnTouchOutside(true)后如何监听Dialog消失

来源:互联网 发布:淘宝有好货是正品吗 编辑:程序博客网 时间:2024/06/07 06:16

我们设置点击Dialog以外的区域时Dialog消失的设置如下:

dialog.setCanceledOnTouchOutside(true);

首先看Dialog的 setCanceledOnTouchOutside(true)的方法里究竟是什么代码,点击进入Dialog的源码可以看到方法

public void setCanceledOnTouchOutside(boolean cancel) {        if (cancel && !mCancelable) {            mCancelable = true;        }        mWindow.setCloseOnTouchOutside(cancel);    }

以上代码中的mCancelable变量就是我们Dialog另外一个设置是否可消失的方法中设置的.

dialog.setCancelable(true);

接着我们继续看关键代码mWindow.setCloseOnTouchOutside(cancel)

/** @hide */    public void setCloseOnTouchOutside(boolean close) {        mCloseOnTouchOutside = close;        mSetCloseOnTouchOutside = true;    }

既然是点击事件,肯定离不开onTouchEvent()

public boolean onTouchEvent(MotionEvent event) {        if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {            cancel();            return true;        }        return false;    }

上面的mCancelable是dialog.setCancelable设置的,关键我们来看mWindow.shouldCloseOnTouch(mContext, event)方法

 /** @hide */    public boolean shouldCloseOnTouch(Context context, MotionEvent event) {        if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN                && isOutOfBounds(context, event) && peekDecorView() != null) {            return true;        }        return false;    }

根据名字我们都看出我们的关键方法是isOutOfBounds(context, event)

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 = getDecorView();        return (x < -slop) || (y < -slop)                || (x > (decorView.getWidth()+slop))                || (y > (decorView.getHeight()+slop));    }

所以可以看出setCanceledOnTouchOutside(true)的监听其实是通过isOutOfBounds(context, event) 的,所以我们要监听点击其他区域关闭dialog的方法就要重写dialog的onTouchEvent方法,然后将isOutOfBounds中的代码加上,代码如下:

class myDialog extends Dialog{//其他代码略·······//触摸对话框其他区域的监听private void onTouchOutside(){}@Overridepublic boolean onTouchEvent(MotionEvent event) {       //触摸外部弹窗             if (isOutOfBounds(getContext(), event)) {                onTouchOutside();            }            return super.onTouchEvent(event);             }   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));        }}