在 RecyclerView 中创建 ContextMenu

最近正好项目中需要在 RecyclerView 中使用到 ContextMenu。在实现过程中发现,RecyclerView 并不像 ListView 那样,简单几步就可以创建 ContextMenu。

这里简单记录一下一个在 StackOverflow 上找到的在 RecyclerView 中创建 ContextMenu 的方法。

方法

首先在 Fragment 的 onViewCreated 方法或者是 Activity 的 onCreate 方法中添加:

1
registerForContextMenu(mRecyclerView);

然后在 RecyclerView 的 Adapter 中添加一个 position 参数用于记录被长按的 item 的位置,同时还需要添加 position 参数的 Getter & Setter 方法:

1
2
3
4
5
6
7
8
9
private int position;

public int getPosition() {
return position;
}

public void setPosition(int position) {
this.position = position;
}

然后让 ViewHolder 实现 OnCreateContextMenuListener 接口,并重写 onCreateContextMenu 方法,给 itemView 设置 OnCreateContextMenuListener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener{

public TextView textView;

public RecyclerViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.textView);
itemView.setOnCreateContextMenuListener(this);
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
//menuInfo is null
menu.add(Menu.NONE, R.id.ctx_menu_mark, Menu.NONE, R.string.ctx_menu_mark);
menu.add(Menu.NONE, R.id.ctx_menu_remove, Menu.NONE, R.string.ctx_menu_remove);
}
}

在 Adapter 的 onBindViewHolder 方法中给 holder.itemView 设置 OnLongClickListener 用于在 ContextMenu 加载之前获得 item 的 position:

1
2
3
4
holder.itemView.setOnLongClickListener((View view) -> {
setPosition(holder.getAdapterPosition());
return false;
});

onViewRecycled 中移除 OnLongClickListener 防止出现引用问题(这一步不一定是必需的):

1
2
3
4
5
@Override
public void onViewRecycled(@NonNull RecyclerViewHolder holder) {
holder.itemView.setOnLongClickListener(null);
super.onViewRecycled(holder);
}

最后在 Fragment 或者是 Activity 中覆盖 onContextItemSelected 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public boolean onContextItemSelected(MenuItem item) {
int position = recyclerViewAdapter.getPosition();
switch (item.getItemId()) {
case R.id.ctx_menu_mark:
// Do your stuff here
Toast.makeText(this, "You clicked mark.", Toast.LENGTH_SHORT).show();
break;
case R.id.ctx_menu_remove:
// Do your stuff here
Toast.makeText(this, "You clicked remove.", Toast.LENGTH_SHORT).show();
break;
}
return super.onContextItemSelected(item);
}

效果图

效果图略大(3.8 MB),加载比较慢,请见谅。

Buy me a cup of coffee