2010年8月18日水曜日

ソースコード内で生成したViewインスタンスにStyleを適用

layout.xmlではstyle属性でStyleを適用できるが、ソース内で直接newしたViewに適用する方法が少しややこしかったのでメモ。

1. 適用したいstyleを作る
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="test">
        <item name="android:textSize">20dip</item>
        <item name="android:textColor">#FF0000</item>
    </style>
</resources>
2. styleを指定するための属性を作る
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <attr name="testStyle" format="integer|reference" />
</resources>
3. Activityに適用しているテーマに、2で作成した属性を使ってstyleへのリファレンスを指定する。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="MyTheme" parent="@android:style/Theme">
        <item name="testStyle">@style/test</item>
    </style>
<resources>
4. コンストラクタに属性IDを渡す
TextView tv = new TextView(context, null, R.attr.testStyle);

Viewのコンストラクタでは、内部的にResources.Theme.obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)が呼ばれている。
このobtainStyledAttributesのdefStyleAttr引数は、上記1~4の通り動作する。defStyleRes引数は、styleリソースのIDを指定できるので、上記のR.style.testを直接引数に指定できる。

Viewのコンストラクタが、defStyle引数をobtainStyledAttributesのdefStyleAttrとdefStyleResの両方に渡してくれればstyleリソースのID直接指定もできると思うんだけど、ソースを見ると何故かdefStyleResに0を渡している。
1855     public View(Context context, AttributeSet attrs, int defStyle) {
1856         this(context);
1857
1858         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
1859                 defStyle, 0);
わざわざテーマに指定するよりも、styleのIDを直接指定できた方が便利なんだけどなー。というか、defStyle引数の説明見ても、styleリソースID指定できるはずなんだけど。。。
「This may either be an attribute resource, whose value will be retrieved from the current theme, or an explicit style resource.」

0 件のコメント:

コメントを投稿