NavigationView的Menu.add仅在onCreate、onResume主体内生效,回调中无效如何解决?
问题根因
- NavigationView的菜单完成首次渲染后,默认不会自动触发重绘,在点击回调、
onNavigationItemSelected这类异步触发的逻辑中调用Menu.add()仅会修改Menu的内存数据,没有通知NavigationView刷新UI,因此看不到新增的菜单项。 - 点击导航菜单项时,DrawerLayout默认会自动关闭抽屉,菜单的刷新动作可能被关闭逻辑拦截,导致即便修改了数据也无法展示。
- 新增菜单项时如果传入的
orderInCategory参数重复,也可能出现新增项被覆盖、排序异常的问题。
修复步骤
1. 修改点击回调逻辑,新增后主动刷新UI
修改onCreate中的菜单项点击监听代码,新增菜单项后主动调用invalidate()通知NavigationView重绘:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mNavigationView = findViewById(R.id.navigation_view); drawerAndToggle();//For drawerlayout setup Menu eventMenu = mNavigationView.getMenu(); MenuItem eventItem = eventMenu.findItem(R.id.add_item); eventItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { // 动态生成不重复的排序值,避免菜单项覆盖 int newOrder = eventMenu.size() + 1; eventMenu.add(R.id.events, Menu.NONE, newOrder, "New item"); // 主动触发NavigationView重绘,展示新增的菜单项 mNavigationView.invalidate(); // 返回true消费点击事件,避免抽屉自动关闭,如果需要关闭可返回false return true; } }); }
2. 修改onNavigationItemSelected逻辑(如果使用该回调处理点击)
@Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { if(item.getItemId() == R.id.add_item){ Menu eventMenu = mNavigationView.getMenu(); int newOrder = eventMenu.size() + 1; eventMenu.add(R.id.events,Menu.NONE,newOrder,"newEvent").setIcon(R.drawable.hangouts_white); // 主动刷新UI mNavigationView.invalidate(); // 如需关闭抽屉可主动调用,不需要则注释 // mDrawerLayout.closeDrawers(); return true; } // 其他菜单项的处理逻辑 return false; }
可选异常排查
如果修改后仍看不到新增项,可检查:
- 新增的菜单项文字/图标颜色是否和NavigationView的背景色一致,可通过
app:itemTextColor、app:itemIconTint属性统一设置菜单项样式 - 目标group
R.id.events是否设置了android:visible="false",可在新增后调用eventMenu.setGroupVisible(R.id.events, true)强制刷新group可见性
内容的提问来源于stack exchange,提问作者Aravind Varma
相关产品推荐
相关产品推荐

