Android Studio开发深色模式切换功能出现无限循环如何解决
Android深色模式切换问题修复方案
问题1:应用重启后无法自动适配深色模式
根因
AppCompatDelegate.setDefaultNightMode() 是进程级配置,应用重启后配置会重置,你当前仅在设置页的onCreate中初始化该配置,启动时未进入设置页就不会触发全局模式设置。
修复步骤
- 自定义全局Application类,在应用启动时就读取SharedPreferences配置设置夜间模式:
public class MyApp extends Application { public static final String MyPREFERENCES= "nightModePrefs"; public static final String KEY_ISNIGHTMODE = "isNightMode"; @Override public void onCreate() { super.onCreate(); SharedPreferences sp = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE); boolean isNightMode = sp.getBoolean(KEY_ISNIGHTMODE, false); if (isNightMode) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); } else { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); } } }
- 在
AndroidManifest.xml的application标签中添加android:name=".MyApp",指定自定义Application。
问题2:切换模式后无限循环
根因
两处逻辑冲突导致循环触发:
- 调用
setDefaultNightMode()后系统会自动重建当前Activity,你又额外手动调用了recreate(),导致重复重建 - 原有代码中
checkNightModeActivated()调用darkSwitch.setChecked()时会触发OnCheckedChangeListener回调,哪怕是代码主动设置的状态,也会再次走切换逻辑,形成死循环
修复步骤
调整设置页代码逻辑:
- 移除
OnCheckedChangeListener中的手动recreate()调用 - 先给Switch设置初始状态,再绑定状态监听,避免代码设置状态时触发不必要的回调
- 调整后的设置页核心代码如下:
private Switch darkSwitch; public static final String MyPREFERENCES= "nightModePrefs"; public static final String KEY_ISNIGHTMODE = "isNightMode"; SharedPreferences sharedPreferences; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_setting); Log.d(TAG_LIFECYCLE, "In the activity_setting onCreate() event"); fbAuth = FirebaseAuth.getInstance(); fbStore = FirebaseFirestore.getInstance(); userID = fbAuth.getCurrentUser().getUid(); sharedPreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE); darkSwitch = findViewById(R.id.swDark); // 先读取状态设置Switch,此时还没设置监听,不会触发回调 boolean isNightMode = sharedPreferences.getBoolean(KEY_ISNIGHTMODE, false); darkSwitch.setChecked(isNightMode); // 再设置监听,仅响应用户点击操作 darkSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); saveNightModeState(true); Log.d(TAG_LIFECYCLE, "In the setting darkModeOn event"); } else { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); saveNightModeState(false); Log.d(TAG_LIFECYCLE, "In the setting darkModeOff event"); } } }); // 原有底部导航逻辑保持不变 BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_nav); bottomNavigationView.setSelectedItemId(R.id.settingActivity); bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { switch (menuItem.getItemId()) { case R.id.mainActivity: startActivity(new Intent(getApplicationContext(),MainActivity.class)); overridePendingTransition(0,0); return true; case R.id.mapActivity: startActivity(new Intent(getApplicationContext(),MapActivity.class)); overridePendingTransition(0,0); return true; case R.id.userInfoActivity: startActivity(new Intent(getApplicationContext(),UserInfoActivity.class)); overridePendingTransition(0,0); return true; case R.id.settingActivity: return true; } return false; } }); } private void saveNightModeState(boolean nightMode) { SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putBoolean(KEY_ISNIGHTMODE, nightMode); editor.apply(); }
注意:如果你的Activity在AndroidManifest.xml中配置了
android:configChanges="uiMode",需要移除该配置,否则系统不会自动触发Activity重建适配新的模式。
内容的提问来源于stack exchange,提问作者zico
相关产品推荐
相关产品推荐

