Android Styling をイチからやり直す
この記事なに?
Android Styling とは Android アプリの見た目を決める一連の仕組みです。Android アプリを作ったことがある人なら必ず触れている基本ですが、ちゃんと理解できていますか? デフォルトで生成された themes.xml
を雰囲気で書いているだけではないですか?
これは僕が Android Styling を使いこなすために今一度イチから勉強し直したまとめです。
間違っていたら教えてください😋
ある特定の View の見た目を変える
Style や Theme の話に入る前に、View の見た目を変える方法を振り返ります。
Android の View の見た目を操作する最も基本の方法は View attribute
です。View attribute は View に外部から設定する値です。xml で設定することが多いです。
例えば TextView の文字色は以下のように変えられます。
<TextView
android:text="サンプル"
android:textColor="#EC407A"
... />
android:textColor
が1つの View attribute です。TextView は他にもたくさんの View attribute を定義しており、開発者は必要に応じてこれらの View attribute に値を設定します。xml で指定した View attribute は TextView のコンストラクタ引数に AttributeSet
として渡され、textColor として設定されます。
もっと深く View attribute について知りたい場合は以下のドキュメントが参考になります。
Creating a View Class | Android Developers
Style と Theme
1つ1つの View に attribute を設定していてはリソースの適用が大変です。View attribute の設定値をUIコンポーネントとして意味のある単位でグループ化し、同じような View に再利用するほうが効率的です。
ここで登場するのが Style
と Theme
です。
Style と Theme の違いは Nick のこの記事がとてもわかり易いです。
Android styling: themes vs styles | by Nick Butcher | Android Developers | Medium
Style は特定の View の View attribute を一括設定するもの
Nick は Style
を Map<View attribute, Resource>
と表現しています。
つまり、設定したい View attribute と設定すべきリソースの値の組が集合したものです。
例えば以下の例は Material Button の Style を拡張して、カスタマイズしたい View attribute を設定しています。
<style name="Widget.MyApp.Button" parent="Widget.MaterialComponents.Button">
<item name="android:textColor">#EF5350</item>
<item name="android:padding">8dp</item>
</style>
Style は特定の View に適用する
Style は複数の View に対して同じ View attribute を設定する用途で利用します。
Style を View に適用するときは style
attribute を使います。
<Button
style="@style/Widget.MyApp.Button"
android:text="ボタン"
... />
親 View や 子 View には Style は伝搬しません。
影響範囲は sytle
attribute を設定した View のみです。
Theme はリソースの参照を提供するもの
他方、Nick は Theme
を Map<Theme attribute, Resource>
と表現しています。 Theme attribute
とは、アプリ内で定義したリソース (Style, Color, TextAppearance, etc...) を別のリソースから参照できるように定義する値です。
Theme attribute はリソースの使い道を名前にしたセマンティック名で定義します。
Theme は以下のように定義します。
<style name="MyAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- アプリのメインカラー -->
<item name="colorPrimary">@color/red</item>
<!-- アプリで利用する Material Button の Style -->
<item name="materialButtonStyle">@style/Widget.MyApp.Button</item>
</style>
Theme attribute で設定したリソースを参照する場合は ?attr/[themeAttributeName]
で参照できます。
<Button
android:textAppearance="?attr/textAppearanceButton"
... />
利用する Theme attribute は <style>
タグの中で好き勝手定義して良いものではなく、attrs.xml
で定義しないといけません。
例えば、colorPrimary
は AppCompat の attrs.xml
で定義されています。自分のプロジェクトで attrs.xml
を作ってオリジナルの Theme attribute を定義することもできます。
<attr name="colorPrimary" format="color"/>
Theme は Context に適用する
Theme は Context (Application, Activity, View, etc...) に適用します。
影響範囲は android:theme
を設定したノードから下のノード全てです。
例えば、以下のような View のツリー構造があった場合、MyTheme
の適用範囲は child1
の View と child1
を親に持つ全ての子 View です。
<LinearLayout
android:id="+id/root"
... >
<LinearLayout
android:id="+id/child1"
android:theme="@style/MyTheme">
<!-- child1 以下は MyTheme の attribute が使える -->
<Button
.../>
</LinearLayout>
<!-- child2 は MyTheme の attribute は使えない -->
<Button
android:id="+id/child2"
... />
</LinearLayout>
ここでいう Theme を適用する
とは、Theme に設定された Theme attribute を利用できる状態にするという意味になります。
View attribute の設定はできるだけ Theme attribute を経由する
layout.xml に書いた View や自分で定義した Style で設定する View attribute の値は、できるだけ Theme attribute を経由したほうが良いです。なぜなら、ブランディング変更やダークテーマ対応など、アプリ全体の見た目を変更したい場合、Theme attribute を使ってリソースを間接参照していれば Theme を編集するだけで済みます。
View が直接リソースを参照していると、個々の layout.xml で設定している View attribute の設定値をすべて変更していかないといけなくなります。これは View の増加に伴って作業量が爆発的に増えていき、メンテが大変な layout が出来上がります。
Style や Theme は既存のものをカスタマイズしていく
Android には様々な View attribute, Theme attribute があるため、自分で Style や Theme をイチから作り上げるのは骨が折れます。そのため Android Styling システムは、ビルトインで提供されている Style や Theme を継承し、開発者が必要な attribute だけ変更できるように作られています。
以下の例だと、AppCompat で定義された Theme である Theme.AppCompat.Light.DarkActionBar
を継承し、カスタマイズしたい Theme attribute だけ個別設定しています。
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary"> ... </item>
<item name="colorAccent"> ... </item>
</style>
colorPrimary
, colorAccent
以外の Theme attribute は Theme.AppCompat.Light.DarkActionBar
から引き継いでいます。
他にどんな Theme attribute があるのか気になる人はここで確認できます。めちゃくちゃあります。
View attribute に設定されている値を確認する方法
Style や Theme を継承して attribute を引き継いでいると、具体的にどの値が View attribute に設定されるかわからなくなります。
個人的には、特に xml で明示的に設定していないデフォルト値が一体どの Style/Theme 由来なのかが分かりにくいです。
そんなときは、Android Studio で View に設定されている全ての View attribute を確認できます。
気になる View を選んで、Attributes パネル を見ます。All Attributes
にデフォルト値を含むすべての attribute の設定が表示されています。虫眼鏡アイコンを押せば attribute 名で検索もできます。
Attributes パネルでは設定されているリソース名までしか確認できません。また、Style などで間接的に値を設定されている場合も確認できない気がします。(この辺はよく分かっていないので知ってる人教えて! )
とにかく、表示されないときの条件は不明ですが、Attribute パネルだけではわからないときがあります。
Attribute パネルでわからないときは、実際にアプリを実行して調べる方法があります。
アプリを実行して Layout Inspector で気になる View を選択すると、実際に利用されているリソースのリテラル値が表示されます。
まとめ
Android Styling の基本をまとめました。
この記事では Styling のコアな部分しか触れていません。View attribute が適用される優先順位や、Theme Overlay の細かい挙動など、Styling で知っておくべきことはまだまだあります。Android Developers のドキュメントやブログ記事でたくさん解説されているので、興味のある方はチェックしてみてください!
- Styles and Themes | Android Developers
- Android styling: themes vs styles | by Nick Butcher | Android Developers | Medium
- Android styling: common theme attributes | by Nick Butcher | Android Developers | Medium
- Android Styling: prefer theme attributes | by Nick Butcher | Android Developers | Medium
- Android Styling: themes overlay. In previous articles in this series on… | by Nick Butcher | Android Developers | Medium
Author And Source
この問題について(Android Styling をイチからやり直す), 我々は、より多くの情報をここで見つけました https://qiita.com/mkeeda/items/effbbc27e76b44117d93著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .