1. 程式人生 > >Android PopupWindow 使點選區域外不消失

Android PopupWindow 使點選區域外不消失

原文地址:https://blog.csdn.net/qq402164452/article/details/53353798

預設的popupWindow點選區域外會使popupWindow自動dismiss,如果有一個點選區域外使popupWindow不自動dismiss的需求,該怎麼辦呢?

首先來看popupWindow的兩個重要的boolean屬性mFocusable和mOutsideTouchable。
mFocusable是用來判斷當前的popupWindow是否獲取焦點,可以通過setFocusable(boolean focusable)來設定。
mOutsideTouchable是用來判斷點選當前的popupWindow區域外的touch事件是否有效,可以通過setOutsideTouchable(boolean touchable)來設定,預設值是false。

如果設定popupWindow的setFocusable( true ),那麼設定setOutsideTouchable ( false )是沒有作用的,點選區域外依然會dismiss。來看看mOutsideTouchable屬性的官方宣告:

 /**
     * <p>Controls whether the pop-up will be informed of touch events outside
     * of its window.  This only makes sense for pop-ups that are touchable
     * but
not focusable, which means touches outside of the window will * be delivered to the window behind. The default is false.</p> * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of
* the {@link #update()} methods.</p> * * @param touchable true if the popup should receive outside * touch events, false otherwise * * @see #isOutsideTouchable() * @see #isShowing() * @see #update() */ public void setOutsideTouchable(boolean touchable) { mOutsideTouchable = touchable; }
翻譯下:
控制popupWindow區域外的點選事件是否有效。這個只有在popupWindow能點選但是沒有獲取焦點的情況下才有作用,作用是區域外的點選事件會傳遞到window後面的activity。
如果popupwindow已經在顯示了,只能使popupwindow下一次show或者呼叫update( )使mOutsideTouchable生效。
當mOutsideTouchable為true時,popupwindow可以接收到區域外的點選事件,反之則不行。

當設定popupWindow的setFocusable( false ),那麼設定setOutsideTouchable ( true ) 時,點選區域外會dismiss,setOutsideTouchable 終於起作用了。也就是mOutsideTouchable只有在mFocusable為false的時候才有作用。

當設定popupWindow的setFocusable( false ),設定setOutsideTouchable ( false ) 時會有什麼效果呢?答案是popupWindow是不會dismiss的,但是區域外的點選事件已經傳遞到popupwindow下面的activity了,點選activity下面的控制元件會有作用的。這就坑爹了,點選區域外不消失的效果是做到了,可是點選區域外,也就是popupWindow下面的activity的控制元件例如button時會響應onClickListener的。那該怎麼使activity不分發popupWindow區域外的點選事件呢?

首先了解下android中的事件分發機制
可以參考下我的個人總結: Android 事件分發機制總結

activity中有兩個重要的處理事件的方法dispatchTouchEvent和onTouchEvent。在這裡主要是利用了
dispatchTouchEvent。

dispatchTouchEvent負責事件的分發,呼叫super.dispatchTouchEvent才會往下如ViewGroup傳遞事件。Activity中當dispatchTouchEvent返回false或者true時:事件停止傳遞,沒繼續往下傳遞,事件被消費了。

這裡寫圖片描述

那我們就重寫activity中dispatchTouchEvent,在裡面判斷popupWindow是否顯示來決定是否往下分發事件。

@Override
public boolean dispatchTouchEvent(MotionEvent event){
        if(mPopupWindow!=null&&mPopupWindow.isShowing()){
            return false;
        }
        return super.dispatchTouchEvent(event);
    }

popupWindow的設定:

mPopupWindow=new PopupWindow(selectView, ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT,true);
mPopupWindow.setFocusable(false);
mPopupWindow.setOutsideTouchable(false);
mPopupWindow.showAtLocation(findViewById(R.id.EditActivity_rootView), Gravity.BOTTOM,0,0);

OK,大功告成。現在點選popupWindow區域外終於不會使popupWindow dismiss了,也不會使下面的activity控制元件得到響應了,perfect 完美!

這個可以解決android 6.0 以上點選popupWindow區域外不消失的解決方法。