问题描述
我有一个 recyclerview,我想通过单击打开某些项目的上下文菜单。我通过调用 openContextMenu()
viewHolder.itemView.setonClickListener(v -> activity.openContextMenu(viewHolder.itemView));
我在 setonCreateContextMenuListener
方法中使用 bind
为上下文菜单注册视图。
但是,上下文菜单上的样式与通过长按打开时的样式不同: 与
长按版本似乎正确应用了 Theme.MaterialComponents
主题。使用 View.showContextMenu()
产生与 Activity.openContextMenu()
相同的结果。甚至 View.performlongClick()
也是如此。主题正在以某种方式应用,因为当我向主题添加 android:itemBackground
等元素时,它适用于菜单的两个版本。我还没有想出解释或修复,但如果/当我这样做时会在这里发布。
解决方法
对话框缺乏主题似乎是一个错误,但我现在对原因和解决方法有了更好的理解:
上下文菜单的材质版本旨在从用户单击视图的位置弹出。调用 View.showContextMenu()
、Activity.openContextMenu()
或 View.performLongClick()
的默认版本时不存在该信息。改用 View.performLongClick(float x,float y)
确实会传递信息,从而生成对话框的材质版本。不幸的是,该方法仅适用于 API 24 及更高版本。
一个(相当痛苦的)版本,对于较新版本的 Android 来说表现如预期:
GestureDetectorCompat detector = new GestureDetectorCompat(fa,new ClickListener(viewHolder.itemView));
viewHolder.itemView.setOnTouchListener((v,event) -> detector.onTouchEvent(event));
使用手势监听器:
private static class ClickListener extends GestureDetector.SimpleOnGestureListener {
public View view;
public ClickListener(View view) {
this.view = view;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return view.performLongClick(event.getX(),event.getY());
}
return view.performLongClick();
}
@Override
public void onLongPress(MotionEvent event) {
onSingleTapConfirmed(event);
}
}
似乎应该有一种更简单的方法,所以如果你找到了,请分享!