Android - Как определить, включен ли ночной режим при использовании AppCompatDelegate.MODE_NIGHT_AUTO
Я использую встроенные функции Android в режиме день / ночь, и я хотел бы добавить опцию в свое приложение для AppCompatDelegate.MODE_NIGHT_AUTO
У меня проблема, хотя, потому что мое приложение требует, чтобы определенные вещи были окрашены программно, и я не могу понять, как проверить, считает ли приложение себя в ночном или дневном режиме. Без этого я не могу установить флаг, чтобы выбрать правильные цвета.
призвание AppCompatDelegate.getDefaultNightMode()
просто возвращает AppCompatDelegate.MODE_NIGHT_AUTO, который бесполезен.
Я не вижу ничего другого, что могло бы сказать мне, но должно быть что-то?
12 ответов
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;
}
Если вы разработчик котлина, вы можете использовать приведенный ниже код для определения темного режима.
val mode = context?.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK)
when (mode) {
Configuration.UI_MODE_NIGHT_YES -> {}
Configuration.UI_MODE_NIGHT_NO -> {}
Configuration.UI_MODE_NIGHT_UNDEFINED -> {}
}
Подробнее о режиме темной темы
Очень простое решение - добавить такой строковый ресурс.
res / values /strings.xml
<string name="mode">Day</string>
Рез / значения-ночь /strings.xml
<string name="mode">Night</string>
А потом везде, где нужно это проверить:
if (resources.getString(R.string.mode) == "Day") {
// Do Day stuff here
} else {
// Do night stuff here
}
Но вы НЕ МОЖЕТЕ называть это раньше super.onCreate()
в жизненном цикле деятельности. Он всегда будет возвращать "День" раньшеonCreate
.
чтобы проверить ночной режим, вы можете сделать следующее:
public boolean isNightMode(Context context) {
int nightModeFlags = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
return nightModeFlags == Configuration.UI_MODE_NIGHT_YES;
}
Побитовый оператор в Java (который используется в ответе @ephemient) отличается в 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
}
}
Версия Котлина: ->
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
}
}
Может быть, это просто свойство, которое на самом деле скажет вам, есть ли у вас темный режим?
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
Для 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
}
Идея использования флага
resources.configuration.isNightModeActive
то же самое, что @Carsten. Я бы предложил простую структуру кода.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
resources.configuration.isNightModeActive) {
// code for night mode
} else {
// code for day mode (or less than API-30)
}
У меня возникли проблемы с тестами пользовательского интерфейса, когда я пытался получить текущую тему в каждом коде ответа. Он каждый раз возвращает одно и то же значение.
Поэтому я создаю статическую переменную в классе приложения и получаю тему для тестов пользовательского интерфейса:
@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
}
В классе приложения:
companion object {
@Theme
@RunNone var theme: Int? = null
}
Может быть, кому-то будет полезно!
Я не обнаружил, что это работает после изменения приложения на темную тему с помощью
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
Есть ли способ узнать настройки системы после изменения приложения с помощью этого метода?
Спасибо,
FF