AppCompatThemeを使っていると、background="?attr/colorPrimary"とか指定したりとかありますよね。
分かりにくいですし、
検索もしにくいです、、
もやもやしていて最近やっとなんとなく分かってきたのでまとめたいと思います。
間違っていたら教えて下さい。
@android:*/*
例: @android:style/TextAppearance.Large
これはAndroidのSDKにあるリソースを直接指定するパターンです。
Andorid Studioで定義に飛んでみると今回は以下の様なものが出てきます。
これがdrawableであれば画像などが出てきます。
<style name="TextAppearance.Large">
<item name="textSize">22sp</item>
</style>
?attr/* ,?*
?attr/*も、?*も同じ意味です。
例 : "?colorPrimary
これはAndroidManifestなどで、Activityのテーマに設定されている要素を取り出しています。
これによりテーマによって動的に要素を変更することが可能となります。
今回は以下のように設定されていたのでそれを参照しています。
今回は、最終的には@color/colorPrimaryが利用されることになります。
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
このcolorPrimary
などの要素そのものはSupport LibraryのAppCompat Library内で定義されており、
declare-styleableで定義されています。
Android Studioで定義に飛ぶと以下の様なものが出てきます。
<declare-styleable name="Theme">
<!-- 省略 -->
<attr name="colorPrimary" format="color"/>
<!-- 省略 -->
</declare-styleable>
ちなみにこの要素をプログラムから取り出すには以下のようにします。
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true);
int color = typedValue.data;
?android:attr/*
?android:attr/textAppearanceLarge
こちらもテーマに設定されている要素を取り出しています。
Theme.AppCompat.Light.NoActionBarの継承関係を辿って行くと以下のようにandroid:textAppearanceLargeの設定を見つけ出すことができました。
<style name="Platform.AppCompat" parent="android:Theme">
<!-- 省略 -->
<!-- Text styles -->
<!-- 省略 -->
<item name="android:textAppearanceLarge">@style/TextAppearance.AppCompat.Large</item>
<!-- 省略 -->
</style>
この要素の宣言はSDK内で宣言されているため、android:と付きます。
https://github.com/android/platform_frameworks_base/blob/d59921149bb5948ffbcb9a9e832e9ac1538e05a0/core/res/res/values/themes_material.xml#L54
まとめ
基本的にテーマと連動して変更できるようにするためにテーマの要素を利用していくのが良いと思います。
それ以外はdeclare-styleableを使うか、直接指定したりするほうがよいと思います。