You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView上下文菜单无法获取正确位置执行用户选中操作

问题排查与解决方案:RecyclerView ContextMenu 位置获取错误

我一眼就看到问题所在了——你在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:40:09