Android 应用上的手动暗模式 resume/restart 导致应用主题无法正常工作

Android manual dark mode on app resume/restart causes app theme to not work correctly

你好,我在手动管理深色模式时遇到了一个大问题,所以我马上开始:

应用程序如何工作

在应用程序启动时,第一个 activity 检查 SharedPreferences 是否用户选择启用暗模式或保持亮模式(默认),然后它会根据用户偏好进行相应更改:

编辑:根据 CSmith 的要求,这里是在 activity

中调用主题选择器的时间
//FirstActivity
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AppThemeSelector.checkAndShowTheme(getApplicationContext());
...

这里是主题选择器方法

//AppThemeSelector.class
    public static void checkAndShowTheme(Context context){
        SharedPreferences sharedPreferences = context.getSharedPreferences(
                PreferencesValues.SHARED_DARKMODE_MAP, Context.MODE_PRIVATE
        );

        boolean darkMode = sharedPreferences.getBoolean(PreferencesValues.SHARED_DARKMODE_ENABLED, false);

        if(darkMode){
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
        }else{
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        }
    }

到目前为止一切顺利,无论何时启动,它都会将其主题设置为用户选择的主题,并且一切正常。

问题发生在哪里

显然这个问题似乎只发生在我的小米 Mi A2 lite (Android 10) 上,因为我已经在 Pixel 2 (Android 11) 和模拟器 (Android 10) 当应用程序从最近的应用程序恢复时一切正常。

问题

重现我的问题的一致方法是: 假设我的应用程序设置为手动灯光模式,并且我的系统处于黑暗模式。我打开应用程序(呆在家里 activity 或去另一个地方 activity 会导致同样的问题)然后我进入系统设置并更改系统语言。 当我从最近的应用程序选项卡重新打开该应用程序时,该应用程序似乎试图重新启动,但它在中途崩溃了(对此不确定,因为 logcat 没有显示任何关于崩溃的信息,应用程序也没有显示任何关于崩溃的对话框)以及何时启动它会自动将其主题设置为系统主题(因此在我的示例中它会进入暗模式)。

此时的问题是,一些本应在深色模式下显示的文本现在有了浅色模式主题,使它们与黑色背景融为一体;应用程序中用于从暗模式更改为亮模式的开关保持正确设置(显示未启用暗模式)但应用程序处于暗模式。如果应用程序重新启动,一切都会恢复正常,并且应用程序会正确显示为浅色主题。

当应用程序在后台停留很长时间时,我无法重现该问题,但我认为它也可能发生。

感谢您的宝贵时间!

我认为您的问题很可能是因为 Andriod Q 及更高版本中的强制黑暗模式。 MIUI 以某种奇怪的方式实现了它,它将每个应用程序转换为黑暗模式。你应该在你的浅色主题样式文件中使用它

<item name="android:forceDarkAllowed" tools:targetApi="q">false</item>

AppCompatDelegate.setDefaultNightMode() 会导致重新创建活动,我通常执行此检查一次并在 Application class 覆盖中执行此操作。

请尝试将对 checkAndShowTheme() 的调用移动到应用程序 class 覆盖

onCreate 方法
public class MyApplication extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();
        AppThemeSelector.checkAndShowTheme(getApplicationContext());
    }
}

这样 setDefaultNightMode() 在应用程序生命周期的早期被调用一次。

老实说,我不确定为什么小米 Mi A2 表现出不同的行为,我只是建议我成功遵循的一种做法,希望它对你有所帮助。

使用

android:configChanges="uiMode" 

清单中的 activity 标签如下:

<activity
android:name=".MyActivity"
android:configChanges="uiMode" />