Android アプリ全体で統一したデザインスタイルがあると、つぶしが効いて良いですよね。
そのための仕組みとして、Android ではテーマ
というものが設けられています。テーマ
を用いることで、アプリケーション全体の配色を決めたり、文字のスタイルを決めたりすることができるようになります。
一つのテーマ
を全体に適用するだけでよければそれはそれで良いのですが、実際問題としては複数のテーマ
を画面ごとに使い分けることもよくある話かと思います。この画面はフルスクリーンで ActionBar
を消すけど、別の画面ではActionBar
を出す、みたいな。
さて、複数のテーマ
を使う場合、たとえば、Light と Dark でボタンの色みを変えたい、という事が起こります。色合いがよく似ているならともかく、Light と Dark のように大きな違いがある場合は、色の調整をしたほうが良いでしょう。
また、テーマ
は各種のスタイル
を統合するための仕組みでもあります。Button
の見た目、TextView
の文字のスタイルなど、目的別にスタイル
を切り出すことによって、それぞれのスタイル
に命名をすることができます。テーマ
ごとにそのスタイル
を切り替えられるようにしておけば、修正も楽になることでしょう。
Theme で使える属性値
このファイルに、デフォルトで定義されている属性値がリストアップされています。というか、その XML そのものです。
おびただしい量の属性値があるので、そのすべてを使いこなすのは至難の業かもしれませんが、例えばボタンのスタイル
を変えたければ、自分のstyles.xml
にあるテーマ
に、以下の行を追加すればよいのです。
<resources>
<style name="MyTheme" parent="android:Theme.Light">
<item name="android:buttonStyle">@style/MyButtonStyle</item>
</style>
<style name="MyButtonStyle" parent="android:Widget.Button">
</style>
</resources>
これを、テーマ
ごとに使い分けるので
<resources>
<style name="MyTheme" parent="android:Theme.Light">
<item name="android:buttonStyle">@style/MyLightButtonStyle</item>
</style>
<style name="MyAnotherTheme" parent="android:Theme">
<item name="android:buttonStyle">@style/MyDarkButtonStyle</item>
</style>
<style name="MyLightButtonStyle" parent="android:Widget.Button">
</style>
<style name="MyDarkButtonStyle" parent="android:Widget.Button">
</style>
</resources>
となります。これで、すべてのボタンがテーマ
によって指定されたスタイル
になるので、ボタンごとにstyle
属性値を設定する必要がなくなりました。
属性値の解決を遅延させる
この表現が正しいのかよく分かりませんが、直接属性値にスタイル
やdrawable
やstring
などへの参照を設定するのではなく、一旦別の箱を用意してそれを参照し、その箱の実態はテーマかどこかで決めるような、ちょっとまどろっこしいですがそんなやり方があります。
<resources>
<attr name="my_drawable" format="reference"/>
</resources>
を用意しすると、my_drawable
という独自の属性が定義されます。これを用いると、
<resources>
<style name="MyTheme" parent="android:Theme.Light">
<item name="my_drawable">@drawable/my_icon_1</item>
</style>
<style name="MyAnotherTheme" parent="android:Theme">
<item name="my_drawable">@drawable/my_icon_2</item>
</style>
</resources>
と言うように宣言でき、レイアウト上では、
<ImageView
...
src="?attr/my_drawable"
.../>
のように、?attr/属性名
と表記することで、テーマ
によって画像が切り替えられるようになります。これをスタイル
にまとめる属性に応用すれば、Android Framework のテーマ
がやっていることと同じことを、自分でガシガシ作りこんでいくことができます。
継承
テーマ
とスタイル
には継承の考え方があります。
その方法には2種類あり、ひとつにはparent
属性を用いる方法、もうひとつには、.
区切りの命名規則による方法です。
parent
属性は簡単で、親にしたいテーマ
やスタイル
を属性値とすればよいだけです。
ただし、公式のリファレンスに曰く、この方法は「フレームワークのリソースを親として参照する場合に限る」と。
しかし、自分で用意したスタイル
やテーマ
も継承したい場面があるでしょう。そこで.
区切りの命名規則を用います。
<resources>
<style name="MyLightButtonStyle" parent="android:Widget.Button">
</style>
<style name="MyLightButtonStyle.Hoge">
</style>
</resources>
以上のように作ると、MyLightButtonStyle
の属性をMyLightButtonStyle.Hoge
が引き継ぎ、かつMyLightButtonStyle.Hoge
独自の拡張ができるようになります。名前空間を区切る間隔で継承による属性値の引き継ぎができるので、スタイルの整理をする際によく用いられます。
まとめ
同じ画面でのテーマの切り替えがそれほど頻繁にあるかどうかはアプリの仕様に依存することと思いますが、往々にしてとっ散らかって収集がつかなくなりがちなリソースも、これらのテクニックでうまく統合できるようになると、管理コストが減らせてよいですね。