DrawerLayout菜单项仅更新一次后返回Null问题求助
问题描述
我在DrawerLayout导航菜单里添加了一个选项,用来切换NavMenuItemView的文本为“启用深色模式”或“禁用深色模式”,该选项关联SharedPreference(即editor变量)。首次切换时功能正常,能根据当前主题模式显示对应文本;但后续切换时,仅能切换主题颜色,文本变为空白,且night变量返回Null。我尝试在onCreate中调用invalidateOptionsMenu,以及将更新逻辑从onCreateOptionsMenu移至onCreate,均未改变该异常表现。
相关代码
private Toolbar toolbar; private DrawerLayout drawerLayout; private NavigationView navigationView; private NavigationMenuItemView night; Menu menu; String imagesDir; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); toolbar = (Toolbar) findViewById(R.id.main_toolbar); setSupportActionBar(toolbar); drawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout); navigationView = (NavigationView) findViewById(R.id.nav_view); night = drawerLayout.findViewById(R.id.NightMode); navigationView.bringToFront(); navigationView.setNavigationItemSelectedListener(this); ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.open,R.string.close); drawerLayout.addDrawerListener(actionBarDrawerToggle); actionBarDrawerToggle.syncState(); } @SuppressLint("RestrictedApi") @Override public boolean onCreateOptionsMenu(Menu menu) { this.menu = menu; drawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout); night = drawerLayout.findViewById(R.id.NightMode); if (night != null) { if (SplashActivity.isDarkModeOn) { night.setTitle("Disable Dark Mode"); } else { night.setTitle("Enable Dark Mode"); } }else { Toast.makeText(this, "null", Toast.LENGTH_SHORT).show(); } return true; } @Override @SuppressLint("RestrictedApi") public boolean onNavigationItemSelected(@NonNull MenuItem item) { int id = item.getItemId(); switch (id){ case R.id.NightMode: night = drawerLayout.findViewById(R.id.NightMode); if (night != null){ if (SplashActivity.isDarkModeOn) { night.setTitle("Disable Dark Mode"); SplashActivity.editor.putBoolean( "isDarkModeOn", false); SplashActivity.editor.apply(); AppCompatDelegate .setDefaultNightMode( AppCompatDelegate .MODE_NIGHT_NO); } else { night.setTitle("Enable Dark Mode"); SplashActivity.editor.putBoolean( "isDarkModeOn", true); SplashActivity.editor.apply(); AppCompatDelegate .setDefaultNightMode( AppCompatDelegate .MODE_NIGHT_YES); } } break; } drawerLayout.closeDrawer(GravityCompat.START); return true; }
解决方案
核心问题分析
- 直接操作NavMenuItemView实例失效:主题切换后,NavigationView会重新渲染菜单布局,之前通过
findViewById获取的night实例会变成无效引用,导致后续调用时返回Null。 - 状态未同步更新:切换主题后,
SplashActivity.isDarkModeOn的静态变量没有及时反转,导致判断逻辑与实际状态不符。
修改后的代码实现
private Toolbar toolbar; private DrawerLayout drawerLayout; private NavigationView navigationView; Menu menu; String imagesDir; private static final String DARK_MODE_KEY = "isDarkModeOn"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); toolbar = findViewById(R.id.main_toolbar); setSupportActionBar(toolbar); drawerLayout = findViewById(R.id.drawerlayout); navigationView = findViewById(R.id.nav_view); // 从SharedPreference同步初始状态 SplashActivity.isDarkModeOn = SplashActivity.editor.getBoolean(DARK_MODE_KEY, false); navigationView.bringToFront(); navigationView.setNavigationItemSelectedListener(this); ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open, R.string.close); drawerLayout.addDrawerListener(actionBarDrawerToggle); actionBarDrawerToggle.syncState(); // 初始化菜单文本 updateNightModeText(); } // 封装菜单文本更新逻辑 private void updateNightModeText() { Menu navMenu = navigationView.getMenu(); MenuItem nightModeItem = navMenu.findItem(R.id.NightMode); if (nightModeItem != null) { nightModeItem.setTitle(SplashActivity.isDarkModeOn ? "禁用深色模式" : "启用深色模式"); } } @Override public boolean onCreateOptionsMenu(Menu menu) { this.menu = menu; updateNightModeText(); return true; } @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.NightMode: // 反转深色模式状态 SplashActivity.isDarkModeOn = !SplashActivity.isDarkModeOn; // 更新SharedPreference SplashActivity.editor.putBoolean(DARK_MODE_KEY, SplashActivity.isDarkModeOn); SplashActivity.editor.apply(); // 切换主题 AppCompatDelegate.setDefaultNightMode( SplashActivity.isDarkModeOn ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO); // 更新菜单文本 updateNightModeText(); break; } drawerLayout.closeDrawer(GravityCompat.START); return true; }
关键优化点
- 通过Menu对象操作菜单项:不再直接获取NavMenuItemView,而是通过
navigationView.getMenu()获取菜单实例,再通过findItem定位目标选项,避免View实例失效问题。 - 同步状态变量:切换主题时直接反转
SplashActivity.isDarkModeOn的值,确保判断逻辑与实际状态一致。 - 封装更新逻辑:将菜单文本更新代码抽成独立方法,避免重复代码,方便调用。
内容的提问来源于stack exchange,提问作者EagleGrant
相关产品推荐
相关产品推荐

