Android - 如何在使用 AppCompatDelegate.MODE_NIGHT_AUTO 时检测夜间模式是否开启

Android - How to detect if night mode is on when using AppCompatDelegate.MODE_NIGHT_AUTO

我正在使用 Android 内置的 day/night 模式功能,我想为我的应用程序添加一个选项 AppCompatDelegate.MODE_NIGHT_AUTO

我遇到了一个问题,因为我的应用程序需要以编程方式对某些内容进行着色,而且我不知道如何检查该应用程序是否认为自己处于夜间或白天模式。没有它,我无法设置标志来选择正确的颜色。

调用 AppCompatDelegate.getDefaultNightMode() 只是 returns AppCompatDelegate.MODE_NIGHT_AUTO 这是没用的。

我看不出还有什么可以告诉我的,但一定有什么?

int nightModeFlags =
    getContext().getResources().getConfiguration().uiMode &
    Configuration.UI_MODE_NIGHT_MASK;
switch (nightModeFlags) {
    case Configuration.UI_MODE_NIGHT_YES:
         doStuff();
         break;

    case Configuration.UI_MODE_NIGHT_NO:
         doStuff();
         break;

    case Configuration.UI_MODE_NIGHT_UNDEFINED:
         doStuff();
         break;
}

如果你是kotlin开发者那么可以使用下面的代码来判断深色模式

when (context.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK)) {
    Configuration.UI_MODE_NIGHT_YES -> {}
    Configuration.UI_MODE_NIGHT_NO -> {}
    Configuration.UI_MODE_NIGHT_UNDEFINED -> {}
}

有关深色主题模式的更多信息

https://github.com/android/user-interface-samples/tree/main/DarkTheme

Java中的位运算符(在@ephemient的回答中使用)不同 在 kotlin 中,因此对于初学者来说,代码可能不容易转换。这是 kotlin 版本以备不时之需:

    private fun isUsingNightModeResources(): Boolean {
        return when (resources.configuration.uiMode and 
Configuration.UI_MODE_NIGHT_MASK) {
            Configuration.UI_MODE_NIGHT_YES -> true
            Configuration.UI_MODE_NIGHT_NO -> false
            Configuration.UI_MODE_NIGHT_UNDEFINED -> false
            else -> false
    }
}

一个非常简单的解决方案是像这样添加一个字符串资源。

res/values/strings.xml

<string name="mode">Day</string>

res/values-night/strings.xml

<string name="mode">Night</string>

然后在任何需要检查的地方:

if (resources.getString(R.string.mode) == "Day") {
    // Do Day stuff here
} else {
    // Do night stuff here
}

但是您不能在 activity 的生命周期中的 super.onCreate() 之前调用它。它总是 return "Day" 在 onCreate 之前。

对于Xamarin.Android

if (Build.VERSION.SdkInt >= BuildVersionCodes.Froyo)
{
    var uiModeFlags = Application.Context.Resources.Configuration.UiMode & UiMode.NightMask;
    switch (uiModeFlags)
    {
        case UiMode.NightYes:
            // dark mode
            break;
        case UiMode.NightNo:
            // default mode
            break;
        default:
            // default mode
            break;
    }
}
else
{
// default mode
}

我的 UI 测试遇到了问题,当时我试图在每个答案代码中获取当前主题。它每次 return 相同的值。

所以我在 应用程序 class 中创建静态变量并获取 UI 测试的主题:

@Theme
fun Context.getAppTheme(): Int? {
    val theme = when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
        Configuration.UI_MODE_NIGHT_NO -> Theme.LIGHT
        Configuration.UI_MODE_NIGHT_YES -> Theme.DARK
        else -> null
    }

    Application.theme = theme

    return theme
}

申请中class:

companion object {
    @Theme
    @RunNone var theme: Int? = null
}

可能对某人有用!

在使用

将应用程序更改为深色主题后,我发现这一切都不起作用
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

有没有办法知道用这种方法更改应用程序后的系统设置?
谢谢,
FF

也许只是一个 属性 会告诉你是否有黑暗模式?

val Context.isDarkMode
    get() = if (getDefaultNightMode() == MODE_NIGHT_FOLLOW_SYSTEM)
        resources.configuration.uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES
    else getDefaultNightMode() == MODE_NIGHT_YES

要检查夜间模式,您可以执行以下操作:

public boolean isNightMode(Context context) {
    int nightModeFlags = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
    return nightModeFlags == Configuration.UI_MODE_NIGHT_YES;
}

Kotlin 版本:->

fun isDarkMode(context: Context): Boolean {
    val darkModeFlag = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
    return darkModeFlag == Configuration.UI_MODE_NIGHT_YES
}

从 Android 版本 R (30) 开始,在 context.resources.configuration.isNightModeActive 中提供了一个值。

所以你不需要再戴面具了。

onConfigurationChanged 中的示例:

private var _isNightModeActive: Boolean = false

override fun onConfigurationChanged(newConfig: Configuration) {
        _isNightModeActive =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                _resources.configuration.isNightModeActive
            } else {
                newConfig.uiMode and
                        Configuration.UI_MODE_NIGHT_MASK ==
                        Configuration.UI_MODE_NIGHT_YES
            }
    }