RecyclerView上下文菜单无法获取正确位置执行用户选中操作
我一眼就看到问题所在了——你在onContextItemSelected方法里,错误地把菜单选项的ID当成了RecyclerView Item的位置来使用!这就是导致你无法获取正确位置的核心原因。
问题具体分析
看你的MainActivity里的这段代码:
@Override public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { case 0: removeFood(item.getItemId()); // 这里把菜单ID(0)当成了位置 break; case 1: changeFood(item.getItemId()); // 同样,菜单ID(1)不是位置 break; } return super.onContextItemSelected(item); }
你创建菜单时给的0和1是菜单条目的ID,不是RecyclerView中Item的位置。调用removeFood和changeFood时,你传入的是菜单ID,而不是真正的Item位置,自然就会操作错误的条目,甚至出现索引越界的问题。
完整解决方案
我们需要修改三个地方,来正确获取ContextMenu对应的RecyclerView Item位置:
1. 在Adapter的ViewHolder中记录当前位置
首先,在foodadapter的foodviewholder里,添加一个变量保存当前Item的位置,并且在onBindViewHolder时更新这个位置:
public class foodadapter extends RecyclerView.Adapter<foodadapter.foodviewholder> { private List<foodmodel>list; public foodadapter(List<foodmodel> list) { this.list = list; } @Override public foodviewholder onCreateViewHolder(ViewGroup parent, int viewType) { return new foodviewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item,parent,false)); } @Override public void onBindViewHolder(foodviewholder holder, int position) { foodmodel food = list.get(position); holder.txtname.setText(food.u_food); holder.txtdate.setText(food.u_date); holder.txttime.setText(food.u_time); // 新增:给ViewHolder设置当前位置 holder.currentPosition = position; } @Override public int getItemCount() { return list.size(); } public class foodviewholder extends RecyclerView.ViewHolder implements OnCreateContextMenuListener { TextView txtname,txtdate,txttime; Button btn; // 新增:保存当前Item的位置 public int currentPosition; public foodviewholder(View itemView) { super(itemView); txtname = (TextView)itemView.findViewById(R.id.text_food); txtdate = (TextView)itemView.findViewById(R.id.text_date); txttime = (TextView)itemView.findViewById(R.id.text_time); btn = (Button)itemView.findViewById(R.id.btntest); itemView.setOnCreateContextMenuListener(this); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { menu.add(0, 0, 0, "Delete"); menu.add(0, 1, 0, "Change"); } } }
2. 在MainActivity的onContextItemSelected中获取正确位置
接下来,修改MainActivity的onContextItemSelected方法,通过menuInfo获取对应的ViewHolder,进而拿到正确的位置:
@Override public boolean onContextItemSelected(MenuItem item) { // 获取ContextMenu对应的RecyclerView上下文信息 RecyclerView.ContextMenuInfo info = (RecyclerView.ContextMenuInfo) item.getMenuInfo(); // 获取对应的ViewHolder,拿到正确的位置 int position = ((foodadapter.foodviewholder) recyclerView.findViewHolderForItemId(info.id)).currentPosition; switch (item.getItemId()) { case 0: removeFood(position); // 传入正确的位置 break; case 1: changeFood(position); // 传入正确的位置 break; } return super.onContextItemSelected(item); }
3. 补充foodmodel的getKey方法
我注意到你的foodmodel.java代码不完整,getKey方法需要补充完整,否则removeFood和changeFood里的food.getKey()会报错:
public class foodmodel { String u_food,u_date,u_time,key; public foodmodel(){} public foodmodel(String u_food,String u_date,String u_time, String key) { this.u_food = u_food; this.u_date = u_date; this.u_time = u_time; this.key = key; } public Map<String,Object> toMap(){ HashMap<String,Object> result = new HashMap<>(); result.put("u_food",u_food); result.put("u_time",u_time); result.put("u_date",u_date); result.put("key",key); return result; } // 补充完整的getKey方法 public String getKey() { return key; } public void setKey(String key) { this.key = key; } // 其他getter和setter保持不变 public String getU_food() { return u_food; } public void setU_food(String u_food) { this.u_food = u_food; } public String getU_date() { return u_date; } public void setU_date(String u_date) { this.u_date = u_date; } public String getU_time() { return u_time; } public void setU_time(String u_time) { this.u_time = u_time; } }
为什么这样能解决问题?
- 我们在ViewHolder中保存了当前Item的位置,确保每个ContextMenu都能关联到正确的Item位置。
- 通过
RecyclerView.ContextMenuInfo获取到触发菜单的Item的ViewHolder,进而拿到真实的位置,而不是错误地使用菜单ID。
这样修改后,你在ContextMenu中选择删除或修改操作时,就能准确操作对应的RecyclerView条目了。
内容的提问来源于stack exchange,提问作者shinmin
相关产品推荐
相关产品推荐

