popupwindow控制点击空白处是否隐藏

最近有个需求,需要自定义一个通用的popupwindow以供各个项目调用,其中有个需求是,该popupwindow需要能够灵活的控制其点击空白处是否隐藏。
关于这个问题,网上流传最广的解决方式是

PopupWindow mPopupWindow = new PopupWindow();
        // 设置popupWindow,当点击popupWindow外面的时候可以消失
        mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
        mPopupWindow.setOutsideTouchable(true);
        // 设置监听
        mPopupWindow.setTouchInterceptor(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_OUTSIDE && !mPopupWindow.isFocusable()) {
                    // 如果焦点不在popupWindow上,且点击了外面,不再往下dispatch事件:
                    // 不做任何响应,不 dismiss popupWindow
                    return true;
                }
                // 否则default,往下dispatch事件:关掉popupWindow,
                return false;
            }
        });

但是我发现根本就捕捉不到ACTION_OUTSIDE这个状态,也就是说

if (event.getAction() == MotionEvent.ACTION_OUTSIDE && !mPopupWindow.isFocusable()) {
                    // 如果焦点不在popupWindow上,且点击了外面,不再往下dispatch事件:
                    // 不做任何响应,不 dismiss popupWindow
                    return true;
                }

这段代码根本就进不去,我的API版本是Android4.0.3。有兴趣的人可以测试一下其它几个版本的API。
经过测试发现,其实只要你为popupwindow设置了背景,那么点击它之外的空白区域就会默认将该popupwindow给隐藏,如果不为它设置背景,那么就不会隐藏。于是我们的解决方法来了。
方法一:

public void setIsDismissTouchOutside(boolean isDismiss) {
        if(isDismiss){
            ColorDrawable dw = new ColorDrawable(0);
            setBackgroundDrawable(dw);
        }
    }

通过是否为popupwindow设置背景来设置点击空白处是否隐藏。
但是在某些情况,可能我们已经为popupwindow设置了背景,但是又希望能够实现该需求,此时我们该如何解决呢。我们可以参考一下最开始的那段代码,通过捕捉popupwindow的触摸事件来判断是否触摸了popupwindow的外部来实现需求。由于我们无法捕捉到ACTION_OUTSIDE这个状态,所以我们需要通过手动判断来是否触摸了外部
我们来看一张图
这里写图片描述
当我们通过popupwindow的setTouchInterceptor()方法来获取触摸点坐标时,该坐标是以popupwindow的左上角为原点,向右为X正轴,向下为Y正轴的坐标系的坐标。那么我们的解决办法来了

public void setIsDismissTouchOutside(boolean isDismiss) {
        if (isDismiss) {
            setTouchInterceptor(null);
            return;
        }
        // 设置监听
        setTouchInterceptor(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                float x = event.getX();
                float y = event.getY();
                // 获取popupwindow的宽度
                float maxX = getMeasuredWidth();
                // 获取popupwindow的高度
                float maxY = getMeasureHeight();
                // 判断触摸点是否在popwindow范围内,如果不在范围内,消费该点击事件
                if (x <= 0 || y <= 0 || x >= maxX || y >= maxY) {
                    return true;
                }
                // 否则default,往下dispatch事件
                return false;
            }
        });

    }
    /**
     * 测量高度
     * 
     * @return
     */
    private int getMeasureHeight() {
        getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        int popHeight = getContentView().getMeasuredHeight();
        return popHeight;
    }

    /**
     * 测量宽度
     * 
     * @return
     */
    private int getMeasuredWidth() {
        getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        int popWidth = getContentView().getMeasuredWidth();
        return popWidth;
    }

以上代码在Android4.0.3测试通过。
如有错漏之处,欢迎指出,感激不尽

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值