Возможно ли иметь ночной квалификатор для заставки на Android? - PullRequest
0 голосов
/ 29 июня 2019

Фон

Я знаю, что в Android Q появилась новая функция, которая наконец-то поддерживает темную тему (написал здесь об ее обнаружении).

Я также знаю, что есть функция "Ночной свет" ( здесь ), которая делает экран более желтоватым.

ПоддержкаВыбор темы вручную - это то, что я делал годами (используя просто setTheme в первой строке кода onCreate в Activity), но я хочу знать, есть ли что-то автоматическое, что позволит мнеустановить его еще до того, как приложение действительно запустится, на заставке.

Проблема

Кажется, очень старая функция (начиная с API 8!) существовала в Android очень долгое время.с наличием в ресурсах «ночного» квалификатора, и я даже не пробовал его.

К сожалению, потому что «темная тема» и ночные вещи теперь чаще обсуждаются как новые функции ( вот например ), я не могу найти, что это за старый.

Однако, глядя на некоторые статьи и документацию, кажется, что это почти полностью вручную:

  • https://developer.android.com/reference/android/app/UiModeManager.html - говорит, что я могу установить его сам, включая наборэто будет автоматически.Тем не менее, похоже, что это связано с тем, чтобы быть состыкованным, и, возможно, даже в автомобильном режиме.course-concept / ru / Unit% 202 / 53_c_providing_resources_for_adaptive_layouts.html - говорит, что я могу установить "ночь" в качестве квалификатора, и есть "ночной режим".

ЧтоЯ пытался

Я пытался установить различные темы соответственно:

res / drawable / splash.xml

  <layer-list xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:opacity="opaque" tools:ignore="UnusedAttribute">
    <item android:gravity="fill">
      <shape android:shape="rectangle">
        <solid android:color="#fff"/>
      </shape>
    </item>
    ...
  </layer-list>

res / drawable-v29 / splash.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:opacity="opaque" tools:ignore="UnusedAttribute">
  <item android:gravity="fill">
    <shape android:shape="rectangle">
      <solid android:color="?attr/colorSurface"/>
    </shape>
  </item>
  ...
</layer-list>

res / drawable-night / splash.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:opacity="opaque" tools:ignore="UnusedAttribute">
  <item android:gravity="fill">
    <shape android:shape="rectangle">
      <solid android:color="#000"/>
    </shape>
  </item>
  ...
</layer-list>

манифест

res / values ​​/ themes.xml

  <style name="AppTheme_splash" parent="@style/Theme.MaterialComponents.DayNight">
    <item name="android:windowBackground">@drawable/splash</item>
  </style>

res / values-v26 / themes.xml

  <style name="AppTheme_splash" parent="@style/Theme.MaterialComponents.DayNight">
    <item name="android:windowSplashscreenContent">@drawable/splash</item>
  </style>

Я пытался удалить android:windowBackground и android:windowSplashscreenContent, пытаясь проверить, работает ли он автоматически, но это не помогло.

Вопросы

В основном я просто хочу узнать о ночном режиме, и если я могу использовать его для заставки:

  1. Когда «ночной режим», поддерживаемый Android, так долго срабатывает?

  2. Это режим os-global?Управляет ли он пользователем?

  3. Это автоматически?Или полностью вручную текущим приложением?

  4. Сохраняется ли режим позже, даже если я установил его вручную в приложении и приложение было убито?

  5. Можно ли установить тему приложения (т.е. для заставки), чтобы использовать ее, чтобы при включенном ночном режиме она использовалась для создания темного фона?

  6. Правильно ли мой код для этого?

1 Ответ

0 голосов
/ 30 июня 2019

1) Эти квалификаторы ресурсов не запускают его автоматически, они использовались для обеспечения общесистемных обратных вызовов и ресурсов для автоматической функциональности Android, можно было изменить этот режим, но он был системным, поэтому его не поощряли использовать в ночном режиме;

2) Новый ночной режим является глобальным параметром, но он работает по-разному на разных уровнях API, но id использует старый квалификатор ресурса "night".

3) Старый "night"Режим был автоматическим и охватывал всю систему, и он был запущен, когда устройство было установлено на док-станцию, и спустя некоторое время, например, в 18:00 (подумайте о автомобильной навигации, которая переключается в темный режим, когда на улице темно, для этого и было предназначено).Если ваше приложение поддерживает, что ваше действие получит обратный вызов, а действие перезапустится и будет использовать ночные ресурсы.«Новый» ночной режим использует те же ресурсы, но они добавили новый API для переключения ресурсов вместо того, чтобы перезванивать, вы спрашиваете систему, какой режим используется, и соответственно настраиваете свои ресурсы (у вас могут быть действия, использующие разные режимы, так как вы явно говоритекакие ресурсы следует использовать).Короче говоря, полностью вручную.

4) Эта опция не сохраняется, если вы хотите сохранить настройку, например, если пользователь использует ваше приложение и он хочет, чтобы ваше приложение было темным независимо от настроек системыВы должны сохранить его настройки и обработать его при запуске приложения.В противном случае приложение запустится в режиме по умолчанию (который светится, даже если настройка системы установлена ​​на темное значение).

5) Да, возможен ночной режим уровня приложения (вы просто указываете системе использовать"ночные" ресурсы для вашего приложения в вашем методе Application.onCreate ().

6) Ваш код частично верен, вам также необходимо сообщить системе об использовании этих ресурсов.

class MyApp : Application() {
// shared pref setting to save user preference for our app. Add your own implementation of shared pref here, I use dependency injection to get the shared preferences
    private val sharedPreferences: SharedPreferencesWrapper by inject() 

    override fun onCreate() {
        super.onCreate()

    // here we say to the system witch resources our application should use since we handle this in application level this will affect all out activities and the splash screen, but we could set it for individual activities as well
    // i'm using a lambda here to listen to when the user changes the setting inside our app and the framework will handle the activities restart
        preferences.nightMode.onChange(true) {
           when (sharedPreferences.nightMode) {
               AppCompatDelegate.MODE_NIGHT_YES -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)  // our app want to be light so it will use default resouces
               AppCompatDelegate.MODE_NIGHT_NO -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) // our app wants to be dark so it will use the "night" resources
               AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY) // our app wants to be dark if on battery saving (because there was no nigh-mode setting that the user had access to on API < Q) this is recommended by google
               AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) // our app wants to follow the system setting (this is only available in Q+ in API < Q if we use this is does nothing) 
            }
        }
    }
}

Теперь вы просто помещаете свои "ночные" ресурсы в папки yourResource-night, которые могут быть чем угодно, например: drawable / drawable-night, values ​​/ values-night "Я выбрал 2 стиля: один светлый, один темный

в values ​​/ styles.xml

<resources>
    <style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <!-- Customise your theme here. -->
        <!--status bar-->
        <item name="android:statusBarColor">@color/light_background</item>
        <!--background-->
        <item name="android:colorBackground">@color/light_background</item>
        <item name="android:windowBackground">@color/light_background</item>
    </style>
</resources>

и в values-night / styles.xml

<resources>
    <style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <!-- Customise your theme here. -->
        <!--status bar-->
        <item name="android:statusBarColor">@color/dark_background</item>
        <!--background-->
        <item name="android:colorBackground">@color/dark_background</item>
        <item name="android:windowBackground">@color/dark_background</item>
    </style>
</resources>

Из документации "Обратите внимание, что андроид в темной тематике:Рисованные окна windowBackground работают только на Android Q. "

Теперь последний шаг - убедиться, что наша деятельность расширяет активность Appcompat

class MainActivity : AppCompatActivity(){}

Я использую приведенную ниже версию из-за некоторых улучшенийкак деятельность ресткогда тема изменилась (раньше было какое-то мерцание)

implementation "androidx.appcompat:appcompat:1.1.0-beta01"

Я тестировал все на API 21+ и работает как положено

...