如何实现Android ListView每一项内的按钮点击弹出ContextMenu
问题原因
你原有代码崩溃的核心原因是:在按钮点击事件中重复给按钮注册上下文菜单,且子项内的按钮不属于ListView的根item视图,系统无法生成对应子项的AdapterContextMenuInfo,触发空指针异常。
解决方案(共2种,推荐使用方案1)
方案1:使用PopupMenu实现(适配点击按钮弹出菜单的场景,逻辑更简洁)
不需要给ListView注册ContextMenu,也不需要重写onCreateContextMenu、onContextItemSelected方法,直接在ListView适配器的getView方法中给每个子项的按钮设置点击逻辑即可:
// 以下代码写在Adapter的getView方法中 button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 存储当前子项位置,后续可通过position获取对应列表数据 final int currentPosition = position; // 创建PopupMenu,第二个参数为锚点View,菜单会自动显示在按钮下方 PopupMenu popupMenu = new PopupMenu(YourActivity.this, v); // 加载你已有的菜单布局 popupMenu.getMenuInflater().inflate(R.menu.menuset, popupMenu.getMenu()); // 设置菜单标题 popupMenu.getMenu().setHeaderTitle("Set as"); // 菜单选项点击处理 popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.as_ringtone: Toast.makeText(YourActivity.this, "TryRingtone,当前子项位置:" + currentPosition, Toast.LENGTH_SHORT).show(); return true; case R.id.as_notify: Toast.makeText(YourActivity.this, "Try Notification,当前子项位置:" + currentPosition, Toast.LENGTH_SHORT).show(); return true; default: return false; } } }); popupMenu.show(); } });
方案2:继续使用ContextMenu实现
保留你原有onCreateContextMenu、onContextItemSelected的逻辑,修改按钮点击事件即可:
- 保留Activity初始化时给ListView注册ContextMenu的代码:
registerForContextMenu(listView_songs);
- 在Adapter的
getView方法中给按钮设置点击事件:
button.setTag(position); // 存储当前子项位置 button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int currentPos = (int) v.getTag(); // 拿到当前子项的根View View itemView = listView_songs.getChildAt(currentPos - listView_songs.getFirstVisiblePosition()); // 打开子项的上下文菜单 openContextMenu(itemView); } });
- 优化
onContextItemSelected逻辑,拿到当前点击的子项位置:
@Override public boolean onContextItemSelected(@NonNull MenuItem item) { // 获取子项信息 AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); int currentPosition = menuInfo.position; if(item.getItemId() == R.id.as_ringtone){ Toast.makeText(this, "TryRingtone,当前子项位置:" + currentPosition, Toast.LENGTH_SHORT).show(); return true; }else if(item.getItemId() == R.id.as_notify){ Toast.makeText(this, "Try Notification,当前子项位置:" + currentPosition, Toast.LENGTH_SHORT).show(); return true; }else{ return false; } return super.onContextItemSelected(item); }
内容的提问来源于stack exchange,提问作者TestingDivine
相关产品推荐
相关产品推荐

