Android RecyclerView长按Item弹出PopupMenu(position=10时)报错求助
我来帮你分析并解决这个问题:
问题根源
你当前用binding.rcvPrefix.getChildAt(position)获取PopupMenu的锚点View,但这个方法有个容易踩的坑:RecyclerView的getChildAt(int index)参数是「可见区域内子View的索引」,而非数据源的position。当position=10时,这个Item大概率不在屏幕可见范围内,getChildAt(10)会返回null,导致PopupMenu没有有效锚点,直接抛出IllegalStateException: MenuPopupHelper cannot be used without an anchor异常。
解决方案:直接传递长按的Item View作为锚点
最可靠的方式是在Adapter的长按监听里,直接把被长按的Item View传给Activity的回调,而不是通过position去RecyclerView里找View。
1. 修改Adapter中的长按回调逻辑
在你的AdapterRcvPrefix里,把长按的View一起传递给Activity:
// Adapter中的Item长按监听 itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { // 传递当前被长按的View和对应的position listener.onRecyclerViewItemLongClicked(getAdapterPosition(), v); return true; } });
同时记得更新你的回调接口定义,添加View参数:
public interface OnItemLongClickListener { void onRecyclerViewItemLongClicked(int position, View anchorView); }
2. 修改Activity中的方法实现
把原来的id参数替换为View anchorView,直接用这个View作为PopupMenu的锚点:
public void onRecyclerViewItemLongClicked(final int position, View anchorView) { // 直接用传递过来的锚点View创建PopupMenu PopupMenu popup = new PopupMenu(MainActivity.this, anchorView); popup.getMenuInflater().inflate(R.menu.menu_item_rcv, popup.getMenu()); popup.show(); popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()){ case R.id.item_add: createDialogAdd(); initializeRCV(); Toast.makeText(MainActivity.this, "Add", Toast.LENGTH_SHORT).show(); break; case R.id.item_edit: Toast.makeText(MainActivity.this, "Edit", Toast.LENGTH_SHORT).show(); break; case R.id.item_delete: Toast.makeText(MainActivity.this, "Delete", Toast.LENGTH_SHORT).show(); db.deletePrefix(prefixList.get(position)); prefixList.remove(position); initializeRCV(); break; default: break; } return true; } }); }
额外提示
- 建议用
getAdapterPosition()而非直接用position,避免Item刷新后位置错乱的问题。 - 如果确实需要通过position获取View,可以用RecyclerView的
findViewHolderForAdapterPosition(int position)方法,它会返回对应position的ViewHolder(即使Item不可见也能返回,但如果Item被回收了会返回null),不过还是直接传递View的方式最稳妥。
内容的提问来源于stack exchange,提问作者Lê Hồng Huy
相关产品推荐
相关产品推荐

