PopupMenu弹出位置的控制
PopupMenu作為彈出菜單是很好用的,但是默認只能彈出在view的下方,而實際中這樣的彈出位置可能無法滿足需求,比如自定義的canvasView,要在canvasView長按的位置彈出菜單,PopupMenu只有一個show的方法,沒有可以設置位置的方法,但當我們跟進源碼去看時發現了這樣的一段代碼:
PopupMenu.class
public void show() {this.mPopup.show();}再對mPopup.show跟蹤時進入到了MenuPopupHelper,又有如下的代碼
public void show() {if (!this.tryShow()) {throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");}}public void show(int x, int y) {if (!this.tryShow(x, y)) {throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");}}public boolean tryShow() {if (this.isShowing()) {return true;} else if (this.mAnchorView == null) {return false;} else {this.showPopup(0, 0, false, false);return true;}}this.mPopup.show調用的是tryShow,而tryShow又調用的是showPopup,在showPopup的參數中有傳入xOffset和yOffset,這說明里面是有傳偏移量的,再仔細看MenuPopupHelper的show函數發現有show(x,y)的重載,如果我們能調用show(x,y),可能就能滿足需求。
但MenuPopupHelper又沒辦法直接得到,是包裝到PopupMenu中的,于是我們采用反射的方式來獲取,代碼如下
Field field = popupMenu.getClass().getDeclaredField("mPopup");field.setAccessible(true);MenuPopupHelper helper = (MenuPopupHelper) field.get(popupMenu);helper.show(x, y);通過反射是得到了MenuPopupHelper,但是會提示錯誤MenuPopupHelper.show can only be called from within the same library group (groupId=com.android.support),跟入到MenuPopupHelper類里面,可以看到有如下圖的限定
為此,我們需要將剛剛反射的部分特別的封裝到一個方法中,并在方法上加入@SuppressLint("RestrictedApi"),這樣就可以正常運行了,代碼如下
public class MenuWorker implements PopupMenu.OnMenuItemClickListener {@SuppressLint("RestrictedApi")private void showPopupMenu(int x, int y) {if (!_drawActivity.isEditing()) {return;}//創建彈出式菜單對象(最低版本11)PopupMenu popupMenu = new PopupMenu(_drawActivity, _view);//第二個參數是綁定的那個view,菜單彈出時默認是顯示該view下方的。initMenu(popupMenu.getMenu());//綁定菜單項的點擊事件popupMenu.setOnMenuItemClickListener(this);//顯示//popupMenu.show();//默認顯示在view的下方,如果要控制具體顯示位置,需要使用反射來實現。try {Field field = popupMenu.getClass().getDeclaredField("mPopup");field.setAccessible(true);MenuPopupHelper helper = (MenuPopupHelper) field.get(popupMenu);y = y - _view.getHeight();//如果y取的是觸摸點的位置,可能需要作此處理,經測試android5.1的設備會彈窗在屏幕之外helper.show(x, y);} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}/*** 初始化菜單** @param menu*/public void initMenu(Menu menu) {menu.clear();menu.add(1, 10001, 0, "添加");menu.add(1, 10002, 1, "刪除");menu.add(1, 10003, 2, "切換");}/*** 菜單點擊** @param menuItem* @return*/@Overridepublic boolean onMenuItemClick(MenuItem menuItem) {switch (menuItem.getItemId()) {case 10001: {//添加break;}case 10002: {//刪除break;}case 10003: {//切換;break;}default:break;}return false;} }轉載請注明出處
總結
以上是生活随笔為你收集整理的PopupMenu弹出位置的控制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 山姆公司关于营销培训方案
- 下一篇: laravel路由的配置,别名,路由群组