【Android】解決PopupWindow點擊外部區域消失后事件透傳致其它View響應點擊事件問題

需求描述

點擊“操作指導”按鈕,在其正下方彈出“產品說明書”、“操作視頻”兩個選項供用戶選擇,點擊PopupWindow外的任意位置關閉彈窗。

預期效果

預期效果.gif


需求實現及異常問題分析

  • 需求實現
      使用PopupWindow顯示內容,通過showAsDropDown(View anchor, int xoff, int yoff)方法顯示在指定按鈕的正下方,使用以下代碼配置來實現點擊PopupWindow內容區域外任意位置關閉彈窗功能:
ColorDrawable dw = new ColorDrawable(0x4c000000);// 新建一個ColorDrawable顏色為半透明
this.setBackgroundDrawable(dw);// 設置SelectPicPopupWindow彈出窗體的背景Drawable
this.setOutsideTouchable(true);// 設置PopupWindow內容區域外的區域是否響應點擊事件(true:響應;false:不響應)

問題來了!!!經過運行操作后發現,在點擊外部區域PopupWindow消失的同時,點擊區域下方如果剛好有View的話,還會響應它的點擊事件(這里是操作指導按鈕,導致該按鈕事件再次觸發彈出PopupWindow)!具體效果如下:

error.gif

  • 異常問題分析
    先來走趟Log吧...我分別在按鈕的點擊事件、PopupWindow的dismiss()方法中添加了如下Log:
 // MainActivity
findViewById(R.id.main_btn_test).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
                Log.e("MainActivity", "show popupWindow.");
                popupWindow.showAsDropDown(view, (view.getWidth() - popupWindow.getWidth()) / 2, 0);
        }
});
    // PopupWindow
    @Override
    public void dismiss() {
        super.dismiss();
        Log.e("PopupWindow", "pop dismiss.");
    }

發生上述異常問題時打印日志如下圖:


error_log.png

通過日志可以看出,因為我們點擊的位置下方剛好存在一個Button,在PopupWindow消失后,事件又進一步傳遞給了Button,從而觸發了Button的點擊事件導致了該問題的發生。


解決方法

那么我們該如何避免點擊PopupWindow外部區域彈窗消失后點擊事件再次向下傳遞呢(透傳給下方的View)?
其實這個方法大多數人都用過,只是很少有人記住——我們可以通過讓PopupWindow聚焦的方式,讓其它子控件獲取不到焦點,從而解決點擊事件透傳的問題,是的,只需要下面一行代碼即可:

this.setFocusable(true);// 聚焦點擊事件不會透傳給下面的View

同時,你會發現,把this.setOutsideTouchable(true);這行代碼注釋掉同樣能達到預期效果,源碼上的邏輯分析。。。未完待續...


【拓展閱讀】
關于PopupWindow的避坑使用,推薦閱讀淺談PopupWindow在Android開發中的使用

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容