AndroidのボタンをXMLのみでスタイリング可能なShapeDrawableで描画するには?
AndroidのボタンをFlexと同様にプログラムを書かずにXMLのみでスタイリングをする方法を模索してきた。
琴線探査: AndroidのボタンをSVGで描画するには?
琴線探査: 続・AndroidのボタンをSVGで描画するには?(ローテクだけど高速版)
琴線探査: AndroidのボタンをShapeDrawableで描画するには?
単純な図形しか描画できないものの、今回である程度満足のいくやり方が固まった。
ボタンのテンプレート(shapeとselector)を作る
まずはres/drawableフォルダを作る。ここに次の3つのファイルを作る。
styleablebutton_up.xml
sytleablebutton_down.xml
styleablebutton.xml
attrs.xmlを作る
次に、このようにvalues/attrs.xmlをつくる。
styles.xmlを作る
次に、このようにvalues/styles.xmlを作る。
このファイルはmain.xmlで楽をするために作ることにした。
しかし、main.xmlでそれぞれのボタン定義で同じ内容を記述する場合は必須ではない。ただ面倒なので作っておいたほうがいい。CSSのクラス定義のようなものだと考えるといい。
スタイリング用カスタムクラスを作る
次に、ex.sdrbパッケージにこのようなStyleableButton.javaクラスを作る。
背景に設定されたStateListDrawable(styleablebutton.xmlのセレクタ)を取得し、そこからUPステートとDOWNステートのDrawableを取得してattrs.xmlで定義したスタイルパラメーター名の値を読み込んで設定していく。
ここではStateListDrawableから取得できるDrawableがGradientDrawableであることがポイント。ShapeDrawableじゃないのね。
main.xmlの編集
res/layout/main.xmlをこのように編集する。
ポイントは
・「xmlns:sdrb」のネームスペースの設定
・「ex.sdrb.StyleableButton」タグでボタン定義
・「style="@style/styleablebutton"」
・「sdrb:fillColorDown」
・「sdrb:fillColorUp」
実行結果
Eclipseプロジェクトファイル:StyleableDrawableResourceButton.zip(160KB)
まとめ
今回はスタイルパラメーターの定義をfillColorのUP、DOWNしかしなかったが、ストロークの幅や色など、attr.xmlとそれに対応するStyleableButton.javaの作り方次第で様々なパラメータ操作をXMLだけで行うことができることがわかった。
簡単なシェイプしか描画できないけど、単に枠を描画したいだけなら9patchを使うよりはるかに柔軟で楽だ。
また、attr.xmlのパラメーター定義は何もスタイリングだけに限らないだろう。パラメーターをメソッドの引数として考えれば、様々な動作をXMLだけで定義することができると思う。
琴線探査: AndroidのボタンをSVGで描画するには?
琴線探査: 続・AndroidのボタンをSVGで描画するには?(ローテクだけど高速版)
琴線探査: AndroidのボタンをShapeDrawableで描画するには?
単純な図形しか描画できないものの、今回である程度満足のいくやり方が固まった。
ボタンのテンプレート(shapeとselector)を作る
まずはres/drawableフォルダを作る。ここに次の3つのファイルを作る。
styleablebutton_up.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#555555" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
<corners android:radius="2dp" />
<stroke
android:width="1dp"
android:color="#FFFFFF" />
</shape>
sytleablebutton_down.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#AAAAAA" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
<corners android:radius="2dp" />
<stroke
android:width="1dp"
android:color="#FFFFFF" />
</shape>
styleablebutton.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/styleablebutton_down" android:state_pressed="true"/>
<item android:drawable="@drawable/styleablebutton_up"/>
</selector>
attrs.xmlを作る
次に、このようにvalues/attrs.xmlをつくる。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="StyleableButton">
<attr name="fillColorUp" format="string" />
<attr name="fillColorDown" format="string" />
</declare-styleable>
</resources>
styles.xmlを作る
次に、このようにvalues/styles.xmlを作る。
このファイルはmain.xmlで楽をするために作ることにした。
しかし、main.xmlでそれぞれのボタン定義で同じ内容を記述する場合は必須ではない。ただ面倒なので作っておいたほうがいい。CSSのクラス定義のようなものだと考えるといい。
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="styleablebutton" parent="@android:style/Widget.Button">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_margin">5dp</item>
<item name="android:padding">5dp</item>
<item name="android:background">@drawable/styleablebutton</item>
<item name="android:textColor">#FFFFFFFF</item>
<item name="android:textSize">10dp</item>
<item name="android:text">StyleableButton</item>
</style>
</resources>
スタイリング用カスタムクラスを作る
次に、ex.sdrbパッケージにこのようなStyleableButton.javaクラスを作る。
package ex.sdrb;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;
import android.util.AttributeSet;
import android.widget.Button;
public class StyleableButton extends Button {
protected Context context;
protected AttributeSet attrs;
public StyleableButton(Context context, AttributeSet attrs) {
super(context, attrs);
this.attrs = attrs;
this.context = context;
StateListDrawable sld = (StateListDrawable) getBackground();
TypedArray styles = context.obtainStyledAttributes(attrs, R.styleable.StyleableButton);
String colorStr;
GradientDrawable gd;
// idx=0はDOWN
colorStr = styles.getString(R.styleable.StyleableButton_fillColorDown);
if (colorStr != null) {
sld.selectDrawable(0);
gd = (GradientDrawable) sld.getCurrent();
gd.setColor(Color.parseColor(colorStr));
}
// idx=1はUP
colorStr = styles.getString(R.styleable.StyleableButton_fillColorUp);
if (colorStr != null) {
sld.selectDrawable(1);
gd = (GradientDrawable) sld.getCurrent();
gd.setColor(Color.parseColor(colorStr));
}
}
}
背景に設定されたStateListDrawable(styleablebutton.xmlのセレクタ)を取得し、そこからUPステートとDOWNステートのDrawableを取得してattrs.xmlで定義したスタイルパラメーター名の値を読み込んで設定していく。
ここではStateListDrawableから取得できるDrawableがGradientDrawableであることがポイント。ShapeDrawableじゃないのね。
main.xmlの編集
res/layout/main.xmlをこのように編集する。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sdrb="http://schemas.android.com/apk/res/ex.sdrb"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp" >
<ex.sdrb.StyleableButton
style="@style/styleablebutton"
android:text="StyleableButton" />
<ex.sdrb.StyleableButton
style="@style/styleablebutton"
sdrb:fillColorDown="#FF4444"
sdrb:fillColorUp="#553333" />
<ex.sdrb.StyleableButton
style="@style/styleablebutton"
sdrb:fillColorDown="#44FF44"
sdrb:fillColorUp="#335533" />
<ex.sdrb.StyleableButton
style="@style/styleablebutton"
sdrb:fillColorDown="#4444FF"
sdrb:fillColorUp="#333355" />
</LinearLayout>
ポイントは
・「xmlns:sdrb」のネームスペースの設定
・「ex.sdrb.StyleableButton」タグでボタン定義
・「style="@style/styleablebutton"」
・「sdrb:fillColorDown」
・「sdrb:fillColorUp」
実行結果
Eclipseプロジェクトファイル:StyleableDrawableResourceButton.zip(160KB)
まとめ
今回はスタイルパラメーターの定義をfillColorのUP、DOWNしかしなかったが、ストロークの幅や色など、attr.xmlとそれに対応するStyleableButton.javaの作り方次第で様々なパラメータ操作をXMLだけで行うことができることがわかった。
簡単なシェイプしか描画できないけど、単に枠を描画したいだけなら9patchを使うよりはるかに柔軟で楽だ。
また、attr.xmlのパラメーター定義は何もスタイリングだけに限らないだろう。パラメーターをメソッドの引数として考えれば、様々な動作をXMLだけで定義することができると思う。

1972 Lincoln Mark Series AC Compressor
返信削除I enjoyed your post. It’s a lot like college – we should absorb everything we can but ultimately you need to take what you’ve learned and apply it.