該文接著上次的PopupWindow之踩坑(1)來說一下它的另外兩個方法,分別是 showAsDropDown(View anchor, int xoff, int yoff)
和showAtLocation(View parent, int gravity, int x, int y)
這兩個都是我們用來show出popupwindowd的方法,但是策略有所不同。
showAsDropDown(View anchor, int xoff, int yoff)方法
這個方法沒有什么好說的,在錨點anchor的正下方彈出popup,參數xoff和yoff分別是x軸和y軸的偏移量,偏移量是相對錨點anchor來說的,以anchor的左下角為參考點;
但是,需要注意的是,Android 7.0版本之前,在指定位置彈出popupwindow用showAsDropDown(View anchor, int xoff, int yoff)毫無問題,但在android 7.0上,用showAsDropDown()就需要注意下面兩點了:
如果指定 PopupWindow 的高度為 MATCH_PARENT,調用 showAsDropDown(View anchor) 時,在 7.0 之前,會在錨點 anchor 下邊緣到屏幕底部之間顯示 PopupWindow;而在 7.0、7.1 系統上的 PopupWindow 會占據整個屏幕(除狀態欄之外)。
如果指定 PopupWindow 的高度為自定義的值height,調用 showAsDropDown(View anchor)時, 如果 height > 錨點 anchor 下邊緣與屏幕底部的距離, 則還是會出現7.0、7.1上顯示異常的問題;否則,不會出現該問題。
所以在無法避免上述的兩個問題時,這時候就需要用showAtLocation()來處理可能出現的popup顯示異常問題。
showAtLocation(View parent, int gravity, int x, int y)
對showAtLocation()方法的很多解釋都是:“相對于父控件的位置,x和y為偏移量。”這種解釋絕對是錯的離譜,而且很可笑,如果是這樣,那它和showAsDropDown()方法還有什么異同,瞪大眼睛看看這個方法的參數,x不再是xoff,y也不再是yoff,從字面上來看也不是什么所謂的偏移量吧,首先,這個方法是對于整個window的屏幕以坐標來定位置的,不存在相對于某一個view,有相對也是相對整個屏幕,參數x和y是坐標。
該方法的第一個參數是parent,類型是個View,這個參數名很讓人誤解,其實,并不是把PopupWindow放到這個parent里,并不要求這個parent是一個ViewGroup。官方文檔對這個參數的解釋是“a parent view to get the token from”,這個parent的作用應該是調用其getWindowToken()方法獲取窗口的Token,所以,只要是該窗口上的控件就可以了。我個人開發中,一般是拿該parent在屏幕中的坐標拿來作為參考的,通過parent.getLocationInWindow(location)
獲得parent在屏幕上的坐標,其中location是一個大小為2的int數組。
第二個參數很讓人理解為對齊方式,當然不是,而是通過設置gravity來設置坐標原點:
- Gravity.TOP | Gravity.LEFT 以屏幕左上角為坐標原點
- Gravity.BOTTOM | Gravity.RIGHT 以屏幕右下角為坐標原點
- Gravity.LEFT 以屏幕左側,屏幕高度 1/2 處為坐標原點
以此類推,可根據實際情況是設置坐標原點的位置。
設置了第二個參數,后面的參數x,y也就是相對于坐標原點的位置了。