Android DataBinding 〜カスタムビューで使う〜

  • 4
    Like
  • 2
    Comment

はじめに

自作したカスタムビューでDataBindingを使う方法についてまとめます。

Step0. 準備

今回は、例としてユーザーの名前(name)と年齢(age)を同時に表示するカスタムビューを作ってみます。

カスタムビュー作成

ユーザー情報は、

User.java
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のレイアウトは、

view_user_info.xml
<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というカスタムビューのクラスを作ってバインドします。

UserInfoView.java
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のレイアウトに組み込みます。

activity_main.xml
<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にデータをセットする口を追加し、バインディングと紐付けます。

UserInfoView.java
public void setUser(User user) {
        mBinding.setUser(user);
}

Step2. BindingAdapterでカスタムセッターを定義

Step1のままでもMainActivity.javaでuser_info.setUser(<User>)するとUserをセットして表示することができますが、xml上で完結する方法もあります。

BindingAdapterアノテーションを使って独自のカスタムセッターを定義でき、これで好きな属性をxmlから指定できるようになります。
例えば、UserをUserInfoViewにセットするカスタムセッターは、以下のように書きます。

BindingAdapters.java
@BindingAdapter("user_data")
public static void setUser(UserInfoView view, User user) {
    view.setUser(user);
}

書くのはどこでも良いのですが、今回はBindingAdaptersというクラスを用意しました。
これでuser_data属性が扱えるようになります。

activity_main.xml
<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")なので注意です。

当然、これは既存のビューにも応用できます。

BindingAdapters.java
@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);
    }
}
activity_main.xml
<TextView
    ...
    app:user_data="@{user}"
    />

Setp3. データを渡す。

あとは、MainActivity.javaからBindingに対してserUser()すれば、
カスタムビューにも反映されます。

binding.setUser(new User("Taro", 6000));

おわりに

以上のように、カスタムセッターを使うと独自のカスタムビューや、既存のビューに用意されていないパラメータに対しても自由にデータバインディングできるようになります。