hiro99ma blog

何か技術的なこと

android: darkモードに手軽に対応したい

2024/10/16

前回 の最後で、自作した Codelabs の課題をダークモードで表示させると全然ダメなことに気付いた。

image

敗因は簡単で、一部だけ Color() を使って固定の色を指定したからだ。
課題のスクリーンショットがあったのでカラーピッカーで取得してそのまま使ったのだ。

カラーテーマを作って、それを反映させるのが通常のやり方らしい。

Material Theme Builderで作って Android 向けを Export。
zip ファイルには Color.kt, Theme.kt, Type.kt が入っていた。

これを何も考えずにプロジェクトの同じファイルに上書きする・・・のはやめよう(やってしまった)。
パッケージ名が com.example.compose になっていたりして、履歴管理していない状態だと名前を探し出すのが面倒だった(大した作業ではないのだが)。

色の選び方は、androidx.compose.material3.MaterialTheme.colorSchemeimport して colorScheme.primary などとすればよさそうだ。
MaterialTheme.colorSchemeLocalColorScheme.current を返すので、AppTheme{}で囲んでいる自作のテーマが使われるようだ。

エミュレータで動かす前に Preview で確認したい場合は、Preview の設定を変更するとよさそうだ。

image

が、いちいち切り替えるのは面倒なので、こちらの @Preview(uiMode=xxx) をそれぞれ用意する方が楽そうだ。

反映されないのはダイナミックカラーの影響

プレビューでライトモードとダークモードはそれぞれ表示されるようになったが、デフォルトのベーステーマというやつでしか表示してくれない。
エミュレータだと反映されているので @Preview() の書き方なのだと思うが、違いが分からん。。。

こちらは API 34 だと反映されないということだったので、私のプレビューもいじってみた。
どうも API 31 以上で反映されないようだ。なして?

Android 12(API 31) の実機(moto g30)で動かしてみたが、期待通りに表示された。
Android 14(API 34) の実機(Pixel7a)で動かすと、こちらはこちらで違う色になった。 が、これは端末側で設定したテーマが反映されるダイナミックカラーというやつだろう。

Android 12 の方ではテーマを設定していなかったか、偶然設定した色と同じようなテーマ色になっていたかだろう。
違う色を設定するとその色で表示された。

ダイナミックカラーが使用できるのは Android 12 以降。
なので、@Preview(apiLevel=30)とすると組み込んだテーマの色がそのまま表示される。
組み込んだテーマ色で見たいなら AppTheme(dynamicColor = false) {} とするのが確実だ。

ダイナミックカラーを有効にしたままテーマを組み込む意味はあるのか

Android 12 より前の機種ではダイナミックカラーがないので、そのためだけになるのか?
それ以降の機種ではダイナミックカラーは必ず設定された状態がデフォルトなのだろうか。 定義値があるところからすると、どれかが設定されるのだろうなあ。

しかし、ダイナミックカラーを有効にしたアプリというのもなかなか難しいかもしれん。
あからさまに変な色になったりはしないのだろうが、なんとなく不安である。

色は全部指定しないといけないのか

Button のように背景色と表の色があるとわかっているものについては onPrimaryprimary が反映されるようだ(色の見た目だけでしか判断してないが)。
しかし Column の中に置いた Text はライトモードでは黒(に見える)、ダークモードでは白(に見える)で描画された。
Column.background()を指定しても変わらなかったので固定色のようだ。
となると、全部の部品について色をまったく指定しないか、全部指定するかのどちらかになるのか?

Surface(contentColor)でそれより下のText()の文字色になるようだ。
“content” がそうなので、ただの color の方もやってくれそうな気がする。

< Top page