PopupWindow常見(jiàn)的問(wèn)題解析

setOutsideTouchable

setOutsideTouchable(true),點(diǎn)擊非PopupWindow視圖區(qū)域,直接隱藏PopupWindow。調(diào)用setOutsideTouchable(true)會(huì)使得點(diǎn)擊非PopupWindow視圖區(qū)域,PopupWindow能夠接收到ACTION_OUTSIDE事件,接收到這個(gè)事件后執(zhí)行dismiss。但是在5.0以下需要調(diào)用setBackground給PopupWindow設(shè)置一個(gè)非空的背景才會(huì)起作用。

小于5.0分析

5.0以下的PopupWindow,當(dāng)mBackground為非null時(shí),才會(huì)創(chuàng)建PopupViewContainer來(lái)封裝contentView,而ACTION_OUTSIDE的處理正是由其來(lái)處理。點(diǎn)擊查看4.4源代碼

    private void preparePopup(WindowManager.LayoutParams p) {
           ......
            if (mBackground != null) {
                ......
                PopupViewContainer popupViewContainer = new PopupViewContainer(mContext);
                ......
                mPopupView = popupViewContainer;
            } else {
                mPopupView = mContentView;
            }
           ......
    }

    private class PopupViewContainer extends FrameLayout {
        ......
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            final int x = (int) event.getX();
            final int y = (int) event.getY();
            
            if ((event.getAction() == MotionEvent.ACTION_DOWN)
                    && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
                dismiss();
                return true;
            } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
                dismiss();
                return true;
            } else {
                return super.onTouchEvent(event);
            }
        }
        ......
    }

大于等于5.0分析

和小于5.0分析類似,大于等于5.0的PopupWindow,不管mBackground是否為null,都會(huì)創(chuàng)建PopupDecorView來(lái)封裝contentView。PopupDecorView會(huì)處理ACTION_OUTSIDE事件。點(diǎn)擊查看5.0源代碼

    ......
    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;
        }

        mDecorView = createDecorView(mBackgroundView);
        ......
    }
    ......
    private PopupDecorView createDecorView(View contentView) {
        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
        final int height;
        if (layoutParams != null && layoutParams.height == WRAP_CONTENT) {
            height = WRAP_CONTENT;
        } else {
            height = MATCH_PARENT;
        }

        final PopupDecorView decorView = new PopupDecorView(mContext);
        decorView.addView(contentView, MATCH_PARENT, height);
        decorView.setClipChildren(false);
        decorView.setClipToPadding(false);

        return decorView;
    }
    ......
    private class PopupDecorView extends FrameLayout {
    ......
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            final int x = (int) event.getX();
            final int y = (int) event.getY();

            if ((event.getAction() == MotionEvent.ACTION_DOWN)
                    && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
                dismiss();
                return true;
            } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
                dismiss();
                return true;
            } else {
                return super.onTouchEvent(event);
            }
        }
    ......
}

setFocusable

調(diào)用setFocusable(true),按back鍵先隱藏PopupWindow而不是整個(gè)Activity。setFoucusable(true)將PopupWindow的mFoucusable設(shè)置為true。在PopupWindow顯示時(shí)如果mFoucusable為false,則會(huì)將FLAG_NOT_FOCUSABLE設(shè)置到Window上,導(dǎo)致系統(tǒng)按鍵事件不會(huì)派發(fā)給PopupWindow。mFoucusable默認(rèn)為false,所以這就是必須調(diào)用setFocusable(true)的原因。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容