美文网首页
PopupWindow 点击外部区域无法关闭的问题

PopupWindow 点击外部区域无法关闭的问题

作者: 冰川孤辰js | 来源:发表于2016-06-06 18:59 被阅读2898次

    [TOC]
    在android4.0/5.0系统上,使用popupWindow时,点击内容外部区域无法关闭,但是在6.0机子上又是正常的,而我在代码中明明已经进行了如下设置:

    mPopupWindow = new PopupWindow(popView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
    // 点击其他地方消失
    mPopupWindow.setOutsideTouchable(true);
    
    点击外部区域不关闭 红色区域是popupwindow内容区域

    google了一下都说要添加一句:

    mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
    

    测试了果然ok,不过还是想知道下所以然,稍微探究一下:
    既然是点击没效果,搜索一下touch事件好了:
    在4.0/5.0的 PopupWindow.java 源码中发现是在 PopupViewContainer 类中设置的,而在6.0源码中则是位于 PopupDecorView 类;

    继续查找在哪里初始化的,发现 preparePopup(),它是在显示(showAtLocation() , showAsDropDown())的时候调用的,而 preparePopup() 的具体内容:

    // PopupWindow.java @ api 14/19/21
    private void preparePopup(WindowManager.LayoutParams p) {
        if (mContentView == null || mContext == null || mWindowManager == null) {
            throw new IllegalStateException("You must specify a valid content view by "
                    + "calling setContentView() before attempting to show the popup.");
        }
    
        if (mBackground != null) {
            final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
            int height = ViewGroup.LayoutParams.MATCH_PARENT;
            if (layoutParams != null &&
                    layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                height = ViewGroup.LayoutParams.WRAP_CONTENT;
            }
    
            // when a background is available, we embed the content view
            // within another view that owns the background drawable
            PopupViewContainer popupViewContainer = new PopupViewContainer(mContext);
            PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, height
            );
            popupViewContainer.setBackgroundDrawable(mBackground);
            popupViewContainer.addView(mContentView, listParams);
    
            mPopupView = popupViewContainer;
        } else {
            mPopupView = mContentView;
        }
        mPopupWidth = p.width;
        mPopupHeight = p.height;
    }
    

    这里可以看到当background不为null的时候,在contentView外面套了一层PopupViewContainer,而PopupViewContainer中才有关于touch,key的监听事件,因此若未设置背景,则点击外部区域无法取消popupwindow,即使设置了:

    mPopupWindow.setOutsideTouchable(true);
    

    而在android6.0中:

    // PopupWindow.java @ api 23
    private void preparePopup(WindowManager.LayoutParams p) {
        ......
    
        // When a background is available, we embed the content view within
        // another view that owns the background drawable.
        if (mBackground != null) {
            mBackgroundView = createBackgroundView(mContentView);
            mBackgroundView.setBackground(mBackground);
        } else {
            mBackgroundView = mContentView;
        }
    
        // 无论background是否为空,都会创建decorView,它是PopupDecorView的实例,其实就是一个FrameLayout,里面有touch事件的监听,因此无需设置背景也可以点击外部区域取消popupwindow的
        mDecorView = createDecorView(mBackgroundView);
        ......
    }
    

    总之,跟网友说的一致,添加背景图片就可以了:

    Bitmap bmp = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.bg_popup_window);
    Drawable drawable = new BitmapDrawable(getContext().getResources(), bmp);
    // 不带参的方法已经deprecated
    popupWindow.setBackgroundDrawable(drawable);
    

    相关文章

      网友评论

          本文标题:PopupWindow 点击外部区域无法关闭的问题

          本文链接:https://www.haomeiwen.com/subject/fnfddttx.html