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; } });
轉載請標明出處: