In daily development, it is common to long press a view to display a menu. Google also provides us with some components to achieve this, such as PopupMenu. But in the actual use or found that it can not meet all our needs.
For example, the product requires the long press menu to appear at the finger position, which is a headache. PopupMenu can only be displayed at the bottom or head of the view. Another problem is that if your view is too long for more than one screen, PopupMenu will not appear on the screen.
So there is no way, can only be forced to scalp themselves a menu. In daily use, I found that the pop-up menu of wechat met the requirements very well, so I imitated wechat to masturbate.
Implementation approach
-
Inherit PopupWindow to implement the long – press popover
-
Gets the current press position and passes it to the view to display
The specific implementation
- The first one is very good implementation, I use recyclerView to achieve the layout, and the incoming resource is
menu
. And the other benefit is to control someitem
(Because I have such a need in my own project, so I took it into consideration)
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());
}
Copy the code
Then it’s time to populate the data into recyclerView
- The second requirement needs to be called
Activity
The rewritedispatchTouchEvent
Get the current click position, and then pass to menu to judge the display position
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);
}
Copy the code
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); }}}Copy the code
Results the following
This is the general idea, finally here is the source code, if you think it is useful to you, welcome to like