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

我正在使用内置在日/夜模式功能的 Android 系统,我想添加一个选项到我的应用程序的 AppCompatDelegate.MODE_NIGHT_AUTO

我有一个问题,虽然因为我的应用程序需要某些东西的颜色编程,我不知道如何检查,如果应用程序认为自己在夜间或白天模式。没有这个,我就无法选择正确的颜色。

调用 AppCompatDelegate.getDefaultNightMode()只会返回 AppCompatgenerate.MODE _ NIGHT _ AUTO,这是无用的。

我看不出还有什么能告诉我的,但肯定有什么?

47071 次浏览
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;
}

If you are kotlin developer then you can use below code to judge dark mode.

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 -> {}
}

For more about dark theme mode

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

The bitwise operator in Java (which is used in @ephemient 's answer) is different in kotlin so the code might not be easily convertible for beginners. Here is the kotlin version just in case someone needs it:

    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
}
}

A very simple solution is to add a string resource like this.

res/values/strings.xml

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

res/values-night/strings.xml

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

And then wherever you need to check it:

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

But you CAN NOT call this before super.onCreate() in an activity's life-cycle. It will always return "Day" before onCreate.

For 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
}

I had problems with my UI tests, when try to get current theme in every answer code. It every time return the same value.

So I create static variable in application class and get theme for UI tests throw it:

@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
}

In Application class:

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

May be it will be usefull for someone!

I found nothing of this to be working after changing the the app to dark theme with

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

Is there any way to know the system setting after changing the app with this method?
Thanks,
FF

Maybe just a property that will actually tell you if you have Dark Mode ?

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

to check for night mode you can do as below:

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

Kotlin Version :->

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

From Android Version R (30) there is provided a value in context.resources.configuration.isNightModeActive.

So you don't need to mask anymore.

Example in 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
}
}