はじめに
自作したカスタムビューでDataBindingを使う方法についてまとめます。
Step0. 準備
今回は、例としてユーザーの名前(name)と年齢(age)を同時に表示するカスタムビューを作ってみます。
カスタムビュー作成
ユーザー情報は、
public class User{
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
で、表示するViewのレイアウトは、
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.databindingcustomview.User" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.name}"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(user.age)}"
/>
<ProgressBar
style="@android:style/Widget.Holo.Light.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="false"
android:max="100"
android:progress="@{user.age}"
/>
</LinearLayout>
</layout>
として、Userの情報がTextViewとProgressBarにそれぞれ表示されるようにしてみます。
user.ageはint型なので、@{String.valueOf(user.age)}
でStringに変換しています。
これをUserInfoViewというカスタムビューのクラスを作ってバインドします。
public class UserInfoView extends LinearLayout {
ViewUserInfoBinding mBinding;
public UserInfoView(Context context){
super(context);
}
public UserInfoView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = LayoutInflater.from(context);
mBinding = DataBindingUtil.inflate(inflater, R.layout.view_user_info, this, true);
}
}
親レイアウトに配置
これをActivityのレイアウトに組み込みます。
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data>
<variable name="user" type="com.example.databindingcustomview.User" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.example.databindingcustomview.UserInfoView
android:id="@+id/user_info"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
</layout>
これでカスタムビューをActivity上に表示するところまでできました。
次にこのビューにUserをセットする方法について説明します。
Step1. カスタムビュークラスにセッターを用意
まず、UserInfoViewにデータをセットする口を追加し、バインディングと紐付けます。
public void setUser(User user) {
mBinding.setUser(user);
}
Step2. BindingAdapterでカスタムセッターを定義
Step1のままでもMainActivity.javaでuser_info.setUser(<User>)
するとUserをセットして表示することができますが、xml上で完結する方法もあります。
BindingAdapterアノテーションを使って独自のカスタムセッターを定義でき、これで好きな属性をxmlから指定できるようになります。
例えば、UserをUserInfoViewにセットするカスタムセッターは、以下のように書きます。
@BindingAdapter("user_data")
public static void setUser(UserInfoView view, User user) {
view.setUser(user);
}
書くのはどこでも良いのですが、今回はBindingAdaptersというクラスを用意しました。
これでuser_data
属性が扱えるようになります。
<com.example.databindingcustomview.UserInfoView
android:id="@+id/user_info"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:user_data="@{user}"
/>
名前空間がandroid:
ではなく、app (xmlns:app="http://schemas.android.com/apk/res-auto")
なので注意です。
当然、これは既存のビューにも応用できます。
@BindingAdapter("user_data")
public static void setUser(TextView view, User user) {
//30以上は赤文字
if (user.getAge() >= 30) {
view.setTextColor(Color.RED);
}else{
view.setTextColor(Color.BLACK);
}
}
<TextView
...
app:user_data="@{user}"
/>
Setp3. データを渡す。
あとは、MainActivity.javaからBindingに対してserUser()すれば、
カスタムビューにも反映されます。
binding.setUser(new User("Taro", 6000));
おわりに
以上のように、カスタムセッターを使うと独自のカスタムビューや、既存のビューに用意されていないパラメータに対しても自由にデータバインディングできるようになります。