xmlファイルを用いてカスタムViewを作る


Androidでは、Viewを自在にカスタムすることが可能です。

Viewをカスタムした例は、以下の記事にも書かれていますので参考にしてみてください。

今回は、タップした際に、指定したアクティビティに画面遷移を行うButtonを作成してみます。さらに、遷移先のアクティビティは、layoutファイルのxmlファイルの属性にて指定できるようにします。
ポイントは以下の点です。

  • attrs.xmlファイルにて、独自に属性を定義する
  • main.xmlファイルにて、独自に定義した属性に値をセットする(カスタムViewをレイアウトに配置)
  • カスタムViewを作成し、独自に定義した属性の値をViewに反映させる

以下が今回のサンプルのキャプチャ画像です。今回は、独自の属性として、ボタンに表示するテキスト、テキストの色、テキストのサイズも設定できるようにしています。

※なお、本文中の「属性」は属性の名称を、「属性値」はその属性にセットされた値をそれぞれ示します。

それでは続きをどうぞ

attrs.xmlファイルにて属性を定義する

まずは、attrs.xmlファイルを作成し、その中に属性を定義します。今回は、ボタンに表示する文字、文字の色、文字のサイズ、アクティビティを属性として定義します。
文字や文字色、サイズは、元々Buttonクラスのメソッドにて指定可能ですが、今回はあえて独自に定義します。

res/values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="CustomView">
    <attr name="text" format="string" />
    <attr name="color" format="color" />
    <attr name="size" format="dimension" />
    <attr name="activity" format="string"/>
  </declare-styleable>
</resources>

nameは属性の名前を、formatは属性値の型をそれぞれ定義しています。

レイアウトのxmlファイルでカスタムViewを定義する
次に、レイアウトxmlファイルでカスタムViewを定義します。ここで、1.で独自に定義した属性に値をセットしてきます。
まずはソースコードを以下に示します。

res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:txt="http://schemas.android.com/apk/res/net.sample.techbooster.customviewsample"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<net.sample.techbooster.customviewsample.CustomVeiw
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    txt:text="SubActivityに遷移"
    txt:color="#f00"
    txt:size="20dp"
    txt:activity="net.sample.techbooster.customviewsample.SubActivity"
    />
</LinearLayout>

まず、3行目を見て下さい。

xmlns:txt="http://schemas.android.com/apk/res/net.sample.techbooster.customviewsample"

ここで、属性が定義されているパッケージを宣言します。この宣言がなかったり、パスを間違えていた場合、後にattrs.xmlファイルに定義した属性値にアクセスする際に定義が見つかりませんと怒られます。

次にカスタムViewをレイアウトに配置します(8から15行目)。
まず、(この後3.で解説する)CustomViewクラスをタグに指定します(8行目)。タグ内の宣言を見てみると、4行目で定義したtxtからattrs.xmlファイルに定義した各種属性にアクセスし、値をセットしています(11〜14行目)。
14行目のactivity属性には、ボタンを押下した際の遷移先アクティビティをセットしています。遷移先のアクティビティを変えたいときは、この属性値を変えるだけで遷移先が変わるよう、次の3.でカスタムViewを作成します。

カスタムViewクラス(ボタン)を作成する。
次に、カスタムViewクラスを作成します。ここで、独自に定義した属性値をViewに反映させます。
今回はButtonを継承したCustomButtonクラスを作成します。
以下が該当のソースコードです。

CustomView.java
public class CustomVeiw extends Button implements View.OnClickListener{

	Context mContext;
	String className;

	public CustomVeiw(Context context, AttributeSet attrs) {
		super(context, attrs);

		mContext = context;
		setOnClickListener(this);

		//attrs.xmlに定義したスタイルのインスタンスを作成
		TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.CustomView);

                //レイアウトファイルで定義した値を取得してButtonにセット
		setText(a.getText(0));
		setTextColor(a.getColor(1, 0));
		setTextSize(a.getDimension(2, 0));
                //遷移先のActivity名を取得
		className = a.getString(3);
	}

	@Override
	public void onClick(View v){
		//ボタン押下時に画面遷移
        	Intent intent = new Intent();
       	 	intent.setClassName(mContext, className);
       		mContext.startActivity(intent);
	}
}

14行目で、attrs.xmlファイルに定義した属性値の値をTypedArray型で取得しています。TypedArrayクラスは、属性値を配列で格納します。getText()メソッドgetColor()メソッド、およびgetDimensions()メソッドにて、 TypedArrayクラスのオブジェクトから各属性値の値を取得し、Buttonにセットしています。
それぞれの第1引数には、TypedArrayオブジェクトに格納された値の格納位置を指定します。attrs.xmlファイルのタグ内での属性の定義順に、0番目から格納されています。第2引数には、属性値がセットされていなかった場合にセットされるデフォルト値を指定しておきます。
onClick()メソッド内では、22行目で取得した、main.xmlファイルで指定したactivity属性の値をsetClassName()メソッドの第2引数にセットし、Intentで画面遷移させています。

あとは、アプリ起動時のActivityで、先ほどのmain.xmlファイルをsetContentView()メソッドの引数に指定します。

CustomViewActivit.java

public class CustomViewActivit extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

以上で、画面にボタンが表示され、タップすると、main.xmlファイルのactivity属性に指定したSubActivityに遷移します。
つまり、遷移先のActivityを変えたい場合は、xmlファイルのtxt:Activity属性を変えるだけで済みます。
以上で、xmlファイルを用いたカスタムビューが完成しました。

関連する記事: