今更だがAndroidでダークテーマを試してみる

Android10でダークテーマが使えるようになりましたが、あんまり触ったことがなかったのでやってみました。

# 一旦DayNight Themeを実装してみよう

DayNight Themeを実装すると、デフォルトではダークモードの変更により画面に変化があるみたいです。
レイアウトにはConstraintLayoutとToolBarだけの状態にしました。

| 基本 | ダークモード |
|:----------------:|:------------------:|
|<img width="200" alt="001_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/37fbac99-c03b-2441-cead-694108ade16b.png">|<img width="200" alt="001_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/aacb4c3c-1bca-7fa4-c464-e8af245ee7e3.png">|

まず基本背景色が黒に変わりますね。背景色を指定していないレイアウトには影響がありそうです。
スクショには見えないですが、テキストのデフォルトカラーも変更されます。
その以外、Material Componentではダークテーマ用のデフォルトカラーが用意されているらしいです。

そしてToolBarの色ですが、これはリソースで色を指定しています。
ダークモードになるとvalues-night配下のリソースが使われるようになります。

```xml:values/colors.xml
<color name="colorPrimary">#6200EE</color>
<color name="toolBarColor">@color/colorPrimary</color>
```

```xml:values-night/colors.xml
<color name="colorPrimary">#BB86FC</color>
```

ToolBarの背景色は`colorPrimary`のリソースを使うようにしています。
その`colorPrimary`がnightリソースで上書きされたため、色が変更になりましたね。
この状態で`toolBarColor`をnightリソースで定義してみました。

```xml:values-night/colors.xml
<color name="colorContents">#212121</color>
<color name="toolBarColor">@color/colorContents</color>
```
|結果|
|:------:|
|<img width="200" alt="002.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/87e7f710-05b8-a8f0-0a08-95bb0fbf4746.png">|

ToolBarの色が変わりました。

# LifeCycleはどうなる？

クイック設定でダークモードのON、OFFをする時、アプリのテーマが切り替わるのですが、その時LifeCycleはどうなるでしょうか。
今はActivityだけあるのでそのままログを書き出してみました。

|結果|
|:------:|
|<img width="274" alt="003.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/27e33a01-6990-9c12-a313-186ba3a0355b.png">|

Destroyまでしちゃいますね。
ではBottomNavigationを入れてFragmentを3つほど入れて試してみます。

|結果|
|:------:|
|<img width="237" alt="004.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/1c271027-ce3f-571c-f2ab-0e2ba668b89a.png">|

やっぱりDetachまで行きます。
SaveInstanceStateを利用してデータを復旧する必要がありそうです。

# 別にDayNight Themeではなくてもシステムのダークテーマ設定はリソースを変更する

DayNight Themeはvalue-nightを指定していない時、デフォルトのダークモード用のカラーが用意されているテーマで、Android10のシステムに追加されてダークテーマはvalue-nightにリソースがあればそれを使うようになっています。
以下は背景はvalue-nightにカラーを指定していて、RadioButtonのスタイルには指定していない時にダークテーマに切り替えた結果です。

| AppCompat.Light.NoActionBar | AppCompat.DayNight.NoActionBar |
|:----------------:|:------------------:|
|<img width="111" alt="006_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/75f8359f-654e-de48-0574-3fcc10f415ca.png">|<img width="113" alt="006_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/9c8210e7-8bd0-c977-bf63-9bd41aa3fb1f.png">|


# アプリの中でLight/Dark Themeに切り替える

システムの設定に寄せなくて、アプリでテーマができるようです。この場合システムの設定は無視されます。

```kotlin:MainActivity.kt
// システムに寄せる
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM)
// ライトテーマ
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO)
// ダークテーマ
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES)
```

|システムはダークテーマにして、アプリはライトテーマにする|
|:------:|
|<img width="237" alt="005.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/c8b44b83-64d3-3749-0c14-e768232dde50.png">|

このコードでの変更はAndroid10ではなくてもテーマが切り替えられます。(api24で試してみました)
そしてこの切り替えの時にも画面は再作成されます。

# まとめ

* DayNight Themeはダークテーマ上のデフォルトカラーを用意しているスタイル
* Android 10に追加された明示的ダークテーマはONの時value-night配下のリソースを使う
* アプリの中でテーマを切り替えられる(Android10ではなくてもいい)
* アプリが起動中でのテーマの切り替えは画面を再作成させる