时间:2021-09-03 09:18:03 | 栏目:Android代码 | 点击:次
在日常开发中,长按某个view出现个菜单是很常见的需求,Google 也给我们提供了一些组件来实现,比如PopupMenu。但是在实际使用中还是发现他无法满足我们的所有需求。
比如:产品要求长按菜单出现在手指按下的位置,额 这就头疼了,PopupMenu只能展示在view的底部或者头部。还有个问题如果你的view过长超过一屏,那么 PopupMenu 就无法显示在屏幕里了。
所以没办法,只能硬着头皮自己撸一个menu了。 在日常使用中发现微信的 弹窗菜单 很符合要求,所以就模仿微信来撸一个了。
实现思路
•继承 PopupWindow 来实现长按弹窗
•获取当前按下 位置,传给 view 来显示
具体实现
•第一个很好实现,我用的是recyclerView 来实现布局的,而且传入的资源是 menu。而且另一个好处就是控制某些 item的可见(因为我自己项目中有这样需求,所以考虑进去了)
private Menu mMenu; @NonNull @SuppressLint("RestrictedApi") public Menu getMenu() { if (mMenu == null) { mMenu = new MenuBuilder(mContext); } return mMenu; } @NonNull public MenuInflater getMenuInflater() { return new MenuInflater(mContext); } public void inflate(@MenuRes int menuRes) { getMenuInflater().inflate(menuRes, getMenu()); }
然后就是填充数据到recyclerView中了
•第二个需求,就需要在调用的Activity 中重写dispatchTouchEvent获取当前点击位置,然后传给 menu 来判断显示位置了
private Point mPoint = new Point(); @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { mPoint.x = (int) ev.getRawX(); mPoint.y = (int) ev.getRawY(); } return super.dispatchTouchEvent(ev); } public void showPopup(View anchorView, int x, int y) { if (!getMenu().hasVisibleItems()) { return; } //set visible item data int size = getMenu().size(); mMenuItems.clear(); for (int i = 0; i < size; i++) { MenuItem item = getMenu().getItem(i); if (item.isVisible()) { mMenuItems.add(item); } } mMenuAdapter.notifyDataSetChanged(); //show int menuHeight = Display.dip2px(mContext, DEFAULT_ITEM_HEIGHT * mMenuItems.size()); if (x <= mScreenPoint.x / 2) { if (y + menuHeight < mScreenPoint.y) { setAnimationStyle(R.style.Animation_top_left); showAtLocation(anchorView, ANCHORED_GRAVITY, x + X_OFFSET, y); } else { setAnimationStyle(R.style.Animation_bottom_left); showAtLocation(anchorView, ANCHORED_GRAVITY, x + X_OFFSET, y - menuHeight); } } else { if (y + menuHeight < mScreenPoint.y) { setAnimationStyle(R.style.Animation_top_right); showAtLocation(anchorView, ANCHORED_GRAVITY, x - mMenuWidth - X_OFFSET, y); } else { setAnimationStyle(R.style.Animation_bottom_right); showAtLocation(anchorView, ANCHORED_GRAVITY, x - mMenuWidth + X_OFFSET, y - menuHeight); } } }
效果如下
大致思路就是这样,最后奉上 源码。
总结