Androidのスタイルリソースとは何か?
概要
Android には <style>
というタグで記述される「スタイルリソース」というものが存在します。
このスタイルリソースにはいくつかの種類が存在していますが、あまり公式のドキュメントにおいてそれらが具体的にどのように利用されるべきなのかが言及されていません。
この文書では AndroidX のコード中でのそれらの具体的な定義や利用方法などを例示しながら、実際の Android アプリケーション開発でどのように定義していけば良いのかを見ていきたいと思います。
スタイルリソースの種類
スタイルリソースとして定義されるリソースにはいくつかの種類があります。
具体的には下記になります。
- テーマ
- スタイル
- テーマオーバーレイ
- テキストアピアランス
これらのリソースは特徴的なプリフィックスを名前(name
属性)に持ち、 Android Studio での名前補完候補にも登場しますので見かけたことのある方も多いのではないかと思います。
各リソースのプリフィックスを下表に示します。
種類 | プリフィックス |
---|---|
テーマ | Theme. |
スタイル | Widget. |
テーマオーバーレイ | ThemeOverlay. |
テキストアピアランス | TextAppearance. |
テーマ
具体的な例をいくつか見ていきましょう。
まずは「テーマ」から。
<style name="Theme.AppCompat.Light.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
これはアプリケーションのテーマの継承元としてよく利用される AndroidX AppCompat で定義されるテーマです。このテーマはTheme.AppCompat.Light
を継承した上でwindowActionBar
とwindowNoTitle
を書き換えたものということですね。
スタイル
次は「スタイル」を見ましょう。
<style name="Widget.AppCompat.TextView" parent="Base.Widget.AppCompat.TextView"/>
これは AppCompat をベースにしたテーマを利用した場合に適用される標準的なTextView
のスタイルになります。このスタイルはBase.Widget.AppCompat.TextView
という別のスタイルを継承しています。スタイルはテーマや API Level に応じて継承元のスタイルを変える必要があり、parent
属性によって継承を行うという記述がよく見られます。
テーマオーバーレイ
次は「テーマオーバーレイ」を見ましょう。
<style name="ThemeOverlay.AppCompat.Dialog.Alert" parent="Base.ThemeOverlay.AppCompat.Dialog.Alert" />
テーマオーバーレイやActionBar
やAlertDialog
を利用する場合によく利用されます。ここではAlertDialog
用のテーマオーバーレイの定義をあげてみました。こちらもスタイルと同様にparent
属性による継承元指定が利用されています。
テキストアピアランス
最後に「テキストアピアランス」を見ましょう。
<style name="TextAppearance.AppCompat.Widget.Button" parent="Base.TextAppearance.AppCompat.Widget.Button" />
これは標準的なButton
用のテキストの見た目を表す定義になります。せっかくなので継承元の定義も見てみましょう。
<style name="Base.TextAppearance.AppCompat.Button">
<item name="android:textSize">@dimen/abc_text_size_button_material</item>
<item name="android:textAllCaps">true</item>
<item name="android:textColor">?android:textColorPrimary</item>
</style>
いかにも「テキストの見た目を表現するために用意されているものである」という感じの定義になっています。
スタイルリソースの使い方
ここまででスタイルリソースにはいくつかの種類があり、それらが実際に AndroidX ライブラリの中で定義されているということを見てきました。本項ではそれらのスタイルリソースが「どのように使われるのか?」あるいは「どのように使えば良いか?」を見ていきたいと思います。
テーマ属性
AndroidX や Material Components for Android の定義するデフォルトのスタイルリソースの多くは、各テーマのテーマ属性のデフォルト値として設定されています。
AppCompat の Light テーマの定義を実際に見てみましょう。
<!-- Platform-independent theme providing an action bar in a light-themed activity. -->
<style name="Theme.AppCompat.Light" parent="Base.Theme.AppCompat.Light" />
すでにTheme.AppCompat.Light.NoActionBar
はご覧いただいた通りです。
ここではその継承元を順に追いかけていきたいと思います。
まずは上記のTheme.AppCompat.Light
が継承元になります。ここではparent
属性を使ってBase.Theme.AppCompat.Light
を継承していますから、さらに継承元を追いかけてみます。
<style name="Base.Theme.AppCompat.Light" parent="Base.V7.Theme.AppCompat.Light">
</style>
こちらもさらに継承元に遡ります。
<!-- Base platform-dependent theme providing an action bar in a light-themed activity. -->
<style name="Base.V7.Theme.AppCompat.Light" parent="Platform.AppCompat.Light">
...
<!-- Button styles -->
<item name="buttonStyle">@style/Widget.AppCompat.Button</item>
<item name="buttonStyleSmall">@style/Widget.AppCompat.Button.Small</item>
<item name="android:textAppearanceButton">@style/TextAppearance.AppCompat.Widget.Button</item>
...
</style>
まだ継承元がありますが、Base.V7.Theme.AppCompat.Light
を見るだけでもなんとなく雰囲気は掴めるのではないかと思います。スタイルリソースが実際にテーマ属性として利用されているということが読み取れるのではないでしょうか。
続いては、各スタイルリソースごとの個別の使い方を見ていきたいと思います。
テーマ
テーマは主に AndroidManifest.xml
の <application>
または <activity>
タグに android:theme
属性として指定します。
Android Studio で新規にアプリケーションを作成したことがある方はご覧になったことがあるかと思います。
その他の使い方としては、コード上でAlertDialog
用のテーマを指定するといった使い方だったり、テーマをよくご存知の方であればContextThemeWrapper
を使ってテーマを書き換えて処理を行うようなコードを書かれたことがある方もいらっしゃるかと思います。
スタイル
スタイルの利用は比較的よく見かけるのではないかと思います。
例えばAlertDialog
のボタン領域のレイアウトではこのように利用されています。
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/buttonPanel"
style="?attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollIndicators="top|bottom">
style
属性でテーマ属性の参照を指定しています。このテーマ属性のTheme.AppCompat.Light
テーマにおける実態はこちらになります。
<item name="buttonBarStyle">@style/Widget.AppCompat.ButtonBar</item>
このように、個別の View に対してstyle
属性を使ってスタイルを指定するという使い方をします。
テーマオーバーレイ
テーマオーバーレイは主に ActionBar や Toolbar と Dialog の実装に使われることが多いです。
また、個別の View に指定して部分的に色を変更するといった用途にも使われます。
テーマオーバーレイの用途については定義箇所に少しだけコメントが記載されていますので、まずはそちらを見てみましょう。
<!-- Theme overlay that replaces colors with their light versions but preserves
the value of colorAccent, colorPrimary and its variants. -->
<style name="ThemeOverlay.AppCompat.Light" parent="Base.ThemeOverlay.AppCompat.Light" />
ご覧の通り、色を置換しますよというコメントが記載されていますね。
次に実際のテーマオーバーレイの定義を見てみましょう。
<style name="Base.ThemeOverlay.AppCompat.Light" parent="Platform.ThemeOverlay.AppCompat.Light">
<item name="android:windowBackground">@color/background_material_light</item>
<item name="android:colorForeground">@color/foreground_material_light</item>
<item name="android:colorForegroundInverse">@color/foreground_material_dark</item>
<item name="android:colorBackground">@color/background_material_light</item>
<item name="android:colorBackgroundCacheHint">@color/abc_background_cache_hint_selector_material_light</item>
<item name="colorBackgroundFloating">@color/background_floating_material_light</item>
...
</style>
色に関する定義だけが記述されているということが見て取れますね。
UIデザインとして「通常利用しているテーマとは異なるテーマを部分的に採用してメリハリをつけたい」とか「部分的にユーザーに与える印象をスッキリさせたい」といった要望が出てくることはよくありますので、そうした場合にテーマオーバーレイを使って部分的に色を変えつつもその色の変え方は共通化するといった対応が可能になります。
それでは実際に利用している箇所を見てみましょう。
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimaryDark"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
こちらはテストコードに含まれているレイアウトリソースになりますが、使い方自体は通常のアプリケーションでも同様です。 android:theme
属性で View のテーマを上書きしています。その下の android:popupTheme
は Toolbar 特有の属性で、こちらもテーマオーバーレイでテーマを上書きしています。
ちなみに、 Dialog のテーマオーバーレイでは色以外の属性も指定されており、 Dialog の見た目だけでなく挙動に影響するような設定も含まれています。テーマオーバーレイにはそうした利用方法もありますが、筆者の経験上、一般的なアプリケーションの開発においてそこまでの知識が必要になることはあまり多くはありません。
テキストアピアランス
テキストアピアランスはその名前の通りテキストの見た目を指定するものです。
TextView を継承した View と、一部のテキスト表示をサポートしている View (例えば Material Components for Android の TabLayout など) で利用することができます。
それでは実際に利用されているコードを見てみましょう。
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/tooltip_margin"
android:paddingLeft="@dimen/tooltip_horizontal_padding"
android:paddingStart="@dimen/tooltip_horizontal_padding"
android:paddingRight="@dimen/tooltip_horizontal_padding"
android:paddingEnd="@dimen/tooltip_horizontal_padding"
android:paddingTop="@dimen/tooltip_vertical_padding"
android:paddingBottom="@dimen/tooltip_vertical_padding"
android:maxWidth="256dp"
android:background="?attr/tooltipFrameBackground"
android:textAppearance="@style/TextAppearance.AppCompat.Tooltip"
android:textColor="?attr/tooltipForegroundColor"
android:maxLines="3"
android:ellipsize="end"
/>
こちらは Tooltip のレイアウトになります。 android:textAppearance="@style/TextAppearance.AppCompat.Tooltip"
となっていますね。このように android:textAppearance
属性で指定してテキストの見た目を設定します。
まとめ
- スタイルリソースにはいくつか種類があります。
- テーマ
- スタイル
- テーマオーバーレイ
- テキストアピアランス
- テーマは主に
AndroidManifest.xml
の<application>
あるいは<activity>
タグのandroid:theme
属性で指定します。 - スタイルは主に View の
style
属性で指定します。 - テーマオーバーレイは主に View の
android:theme
属性(古いプロジェクトではapp:theme
属性)で指定します。 - テキストアピアランスは主に TextView の
android:textAppearance
属性で指定します。
種類 | 名前 | 用途 |
---|---|---|
テーマ | Theme. |
Application / Activity のandroid:theme 属性に指定 |
スタイル | Widget. |
View のstyle 属性に指定 |
テーマオーバーレイ | ThemeOverlay. |
View のandroid:theme 属性に指定 |
テキストアピアランス | TextApperance. |
TextView のandroid:textAppearance 属性に指定 |
Discussion