Delphi はダークモードに対応していない
Delphi はスタイルで見た目をコントロールしているので、ダーク系のスタイルにすればダークモードになるよ、などと一部の記事に書いてありますが、それは残念ながら嘘です。
スタイルでダーク系の色になるのと、ダークモードの対応は全く別の話です。
↓下記の画像はダークモードが有効な端末でダーク系のスタイルにした所です。
ナビゲーションバーが白背景になっています。
↓これはデフォルトのカメラのナビゲーションバーです
ちゃんとダークモードの色(黒背景)になっています。
テーマ
Android ではアプリケーション全体の色調をテーマで指定します。
具体的には styles.xml で↓下のように指定します(parent(継承元)に Android の規定のテーマを指定)。
<style name="AppTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
なお、上記の XML は Delphi が生成したものです。
parent に思いっきり Light が付いているテーマが書いてあります。
これはライトモード用の背景です。
OMG!
生成される styles.xml のテーマを指定できるようになっていれば良いのですが、これを制御する方法は無いようでした(TitleBar の有無だけ指定できます。知っている方が居たら教えてください)。
Delphi でダークモードを指定する
上記の styles.xml ですが実際には下記の3ファイルが生成されます。
- styles.xml
- styles-v21.xml
- styles-v31.xml
Android のバージョンに応じて、このどれかが使われます。
v21, v31 は上記の Light テーマが使われる設定になっているので、これらが使われるとナビゲーションバーが白くなってしまいます。
かといって、styles.xml はビルド時に上書きで自動生成されるため、中身を変えるのは面倒です。
そこで、styles.xml を使わず強制的にテーマを指定してしまうのが最も簡単です。
AndroidManifest.template.xml の中身を書き換えます。
<application
中略
android:theme="%theme%" ←これを
中略
<application
中略
android:theme="@android:style/Theme.NoTitleBar" ←こう!
中略
このように色指定の無いテーマを直接指定してしまえば、自動的にシステムの色でナビゲーションバーが表示されます。
背景色と合致していませんが、これで一応は言い訳が立ちます。
もっとちゃんとやる
背景色と合致してないのかっっこ悪い。
そこで、先ほど面倒と言った事をやります。
まず styles-v31.xml をプロジェクトと同じ場所に作ります。
中身は以下の通りです。
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Theme.Material テーマはダークモードのテーマ -->
<style name="AppTheme" parent="@android:style/Theme.Material.NoActionBar">
<!-- 色指定 -->
<item name="android:navigationBarColor">ここに色を指定</item>
<item name="android:navigationBarDividerColor">ここに色を指定</item>
<item name="android:statusBarColor">ここに色を指定</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<!-- ここから下はオリジナル -->
<item name="android:windowBackground">@color/splash_background</item>
<item name="android:windowClipToOutline">false</item>
<!-- API 31+ specific attributes -->
<item name="android:windowSplashScreenBackground">@color/splash_background</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/splash_vector</item>
<item name="android:windowSplashScreenIconBackgroundColor">@color/splash_background</item>
</style>
</resources>
「ここに色を指定」と書いてある場所(3箇所)は #ffffff という16進数表記や colors.xml の @color で指定します。
色指定について簡単に解説すると下のようになります。
Item 名 | 意味 |
---|---|
navigationBarColor | ナビゲーションバーの背景色 |
navigationBarDividerColor | ナビゲーションバーの境界線の色 |
statusBarColor | ステータスバーの背景色 |
今回はスタイルの背景色と同じ #3c3c3c としました。
この styles-v31.xml を配置マネージャを使ってアプリケーションに含ませます。
配置マネージャを開くと↓このようにデフォルトの styles-v31.xml が登録されているので、これを自作の styles-v31.xml に変更します。
- 自作の styles-v31.xml を配置マネージャに追加します
- 元の styles-v31.xml のチェックを外します。
- 自作の styles-v31.xml の情報を以下のように変更します。
リモートパス:res\value-v31\
リモート名:styles.xml
設定し終わった画面が下図になります。
必要であれば styles-v21.xml も同じように指定してください。
これで、ビルドすると styles-v31.xml が上書きされて背景色がそろったキレイな表示になります…が…
↓下のように線がきえない事もあります!(NavigationBarDivider の色がおかしい)
Android が自動的に scrim と呼ばれる半透明の帯を被せてくる場合があるためです。
scrim をかけてくるかどうかは、NavigationBar の色によります(ユーザーから見てナビゲーションボタンが見えないとシステムが判断すると scrim をかけてきます)。
scrim を勝手にかけないフラグなどがあるのですが、上手く行きませんでした。
(目では解りづらいですがナビゲーションバーの色も暗くなっています)
いっそのこと、↓こんな風に線に色をつけてしまうのもありかもしれません。
なお、線の色として #00ffff
を指定したのですが、scrim のせいで表示された色は #75fbfd
になっていました。
ちなみに、ナビゲーションバーは透過させることができるので、それを使うと NavigationBarDivider は表示されなくなり、この問題は発生しません。
ですが、ナビゲーションバーの裏側までアプリが潜り込むので Margins などを使ってナビゲーションバーに被らないようにしないといけません。
まとめ
楽にやる方法
AndroidManifest.template.xml の android:theme
を "@android:style/Theme.NoTitleBar"
に書き換える。
ちゃんとやる方法
自前の styles-v31.xml (必要であれば styles-v21.xml も)を用意して配置マネージャで置き換える。
線が表示されてしまう場合は、思い切って線に色を付けちゃう。