カスタムviewをxmlで使用する
Android プログラミングで自前で View を継承して作成したカスタムviewをレイアウトファイル(xml)に記述する方法
例えば、時刻を表示するためにTextViewを使っているとして、いちいち
view.setText((new SimpleDateFormat("HH:mm:ss")).format(System.currentTimeMillis()));
などと書くのが面倒だとする。TextView に表示する時刻を持たせて、
view.setTime(System.currentTimeMillis());
としたら、画面には 12:15:07 とか勝手に表示されて欲しいよね。
でも、レイアウトの配置は固定だからレイアウトxmlファイルに自前で作ったクラスを書きたい。
以下手順
1.まずは適当に TextView を拡張したクラスを作成する
public class TimeView extends TextView {
private long time;
private SimpleDateFormat df;
public TimeView(Context context) {
this(context, null, 0);
}
public TimeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TimeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
time = 0;
df = new SimpleDateFormat("HH:mm:ss");
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Date date = new Date(time);
setText(df.format(date));
}
public void setTime(long time) {
if ( time >= 0 ) this.time = time;
invalidate();
}
public long getTime() { return time; }
}
注意点
- TextView の持つ 3種類のコンストラクタを実装する。そうしないと xml ファイルからビューをinflate するところで失敗する
2.作成したクラスをレイアウトファイルに書く
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res/YOUR_PACKAGE_NAME" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <YOUR_PACKAGE_NAME.TimeView android:layout_width="160dp" android:layout_height="wrap_content" android:layout_gravity="center" android:background="#c0c080" /> <Button android:id="@+id/nowButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:onClick="setCurrentTime" android:text="@string/now" /> </LinearLayout>
注意点
- xmlns:app 宣言を追加して、自分のアプリケーションのパッケージ名を記載する
- カスタムビューは完全修飾名で記載する
すると

な感じで組込みのViewと同じように使える。
3.あとは使うだけ
public class MainActivity extends Activity {
private TimeView timeView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
timeView = (TimeView)findViewById(R.id.currentTimeView);
}
public void setCurrentTime(View v) {
timeView.setTime(System.currentTimeMillis());
}
}
View 側でいろいろさせることで、MainActiviy がすっきりしてちょっと嬉しい。

作成したサンプルはここ https://github.com/koko-u/CustomViewSample