PopupWindow 彈窗點選區域外部不消失
預設的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區域外的點選事件呢?
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區域外不消失的解決方法。