自訂PopupWindow,popupwindow
PopupWindow,一個快顯視窗控制項,可以用來顯示任意View,而且會浮動在當前activity的頂部
自訂PopupWindow。
1.extends PopupWindow
2.構造方法中可以進行一些屬性設定
setContentView(View convertView); //設定popupWindow顯示的View
getContentView(); //擷取popupWindow顯示的view
setWidth(mWith); //設定popupWindow的寬度
setHeight(mHeight); //設定popupWindow的高度
設定寬高,也可以在構造方法那裡指定好寬高, 除了可以寫具體的值,還可以用WRAP_CONTENT或MATCH_PARENT, popupWindow的width和height屬性直接和第一層View相對應。
setAnimationStyle(R.style.PopupAnimation); //設定彈齣動畫
setFocusable(true);
設定焦點,PopupWindow彈出後,所有的觸屏和物理按鍵都由PopupWindows 處理。其他任何事件的響應都必鬚髮生在PopupWindow消失之後,(home 等系統層面的事件除外)。 比如這樣一個PopupWindow出現的時候,按back鍵首先是讓PopupWindow消失,第二次按才是退出 activity,準確的說是想退出activity你得首先讓PopupWindow消失,因為不並是任何情況下按back PopupWindow都會消失,必須在PopupWindow設定了背景的情況下。
而setFocusable(false); //PopUpWindow只是一個浮現在當前介面上的view而已,不影響當前介面的任何操作,是一個沒有存在感的東西
一般情況下setFocusable(true);
setTouchable(true); // 設定popupwindow可點擊
要讓點擊PopupWindow之外的地方PopupWindow消失:
1.setOutsideTouchable(true);
2.調用setBackgroundDrawable(new BitmapDrawable()); 設定背景,為了不影響樣式,這個背景是空的。
除此之外,還可以這樣寫,setBackgroundDrawable(new ColorDrawable(0x00000000));背景不空,但是完全透明
經過實際檢驗,只要設定了背景,不管有沒有設定setOutsideTouchable(true);即使設定了setOutsideTouchable(false);一樣能夠實現點擊PopupWindow之外的地方PopupWindow消失,有點奇葩,不過為了保險起見,還是加上setOutsideTouchable(true);比較好。
PopupWindow還有一個方法,也是用來設定點擊PopupWindow外部使得PopupWindow消失的,不過僅僅是實現這個方法是不行的,一樣要設定背景才起作用。可是當設定了背景的時候,下面這個方法不管有沒有用都能夠實現點擊PopupWindow外部使得PopupWindow消失,也是夠醉。
setTouchInterceptor(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(event.getAction()==MotionEvent.ACTION_OUTSIDE) { dismiss(); return true; } return false; } });
設定PopupWindow的彈出位置
popupWindow = new SelectPicPopupWindow(參數);
popupWindow.showAtLocation(findViewById(R.id.settings_layout),
Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);
//在這裡findViewById(R.id.settings_layout)是當前介面的id。
設定了PopupWindow的background,點擊Back鍵或者點擊彈窗的外部地區,彈窗就會dismiss.相反,如果不設定PopupWindow的background,那麼點擊back鍵和點擊彈窗的外部地區,彈窗是不會消失的.
如果我想要一個效果,點擊外部地區,彈窗不消失,但是點擊事件會向下面的activity傳遞,比如下面是一個WebView,我想點擊裡面的連結等.
/** * 點擊外部地區,彈窗不消失,但是點擊事件會向下面的activity傳遞,要給Window設定一個Flag, * WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL * 看了源碼,這個Flag的設定與否是由一個叫mNotTouchModal的欄位控制,但是設定該欄位的set方法被標記為@hide。 * 所以要通過反射的方法調用: * Set whether this window is touch modal or if outside touches will be sent * to * other windows behind it. * */ public static void setPopupWindowTouchModal(PopupWindow popupWindow, boolean touchModal) { if (null == popupWindow) { return; } Method method; try { method = PopupWindow.class.getDeclaredMethod("setTouchModal", boolean.class); method.setAccessible(true); method.invoke(popupWindow, touchModal); } catch (Exception e) { e.printStackTrace(); } }
然後調用setPopupWindowTouchModal(popupWindow, false);就可以了。
不過還有要注意的是:
1.設定了setHeight();假如設定的高度小於螢幕的高,那麼透明的那一部分是不屬於PopupWindow的。
2.設定setContentView(View v);由於v裡面的組件在布局檔案裡並沒有佔滿整個螢幕,例如只是放在了底部,使得彈出PopupWindow上部分出現了透明,這個透明部分還是屬於PopupWindow的,那麼要想做到點擊透明部分使得PopupWindow消失,又該怎麼做呢?
這個也不難,答案如下:
/** *public class SelectPicPopupWindow extends PopupWindow */private View popupView;popupView = inflater.inflate(R.layout.popup_window, null);this.setContentView(popupView);popupView.setOnTouchListener(new OnTouchListener() { @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View v, MotionEvent event) { int height = popupView.findViewById(R.id.popup_layout).getHeight(); int y = (int) event.getY(); if(event.getAction() == MotionEvent.ACTION_UP){ if(y<height) { dismiss(); } } return true; } });