Dave Dave - 2 months ago 164
Android Question

android data binding with a custom view

The Android data binding guide discusses binding values within an activity or fragment, but is there a way to perform data binding with a custom view?

I would like to do something like:

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.mypath.MyCustomView
android:id="@+id/my_view"
android:layout_width="match_parent"
android:layout_height="40dp"/>

</LinearLayout>


with
my_custom_view.xml
:

<layout>

<data>
<variable
name="myViewModel"
type="com.mypath.MyViewModelObject" />
</data>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{myViewModel.myText}" />

</LinearLayout>

</layout>


While it appears possible to do this by setting custom attributes on the custom view, this would quickly become cumbersome if there's a lot of values to bind.

Is there a good way to accomplish what I'm trying to do?

Answer

In your Custom View, inflate layout however you normally would and provide a setter for the attribute you want to set:

private MyCustomViewBinding mBinding;
public MyCustomView(...) {
    ...
    LayoutInflater inflater = (LayoutInflater)
        context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mBinding = MyCustomViewBinding.inflate(inflater);
}

public void setMyViewModel(MyViewModelObject obj) {
    mBinding.setMyViewModel(obj);
}

Then in the layout you use it in:

<layout xmlns...>
    <data>
        <variable
            name="myViewModel"
            type="com.mypath.MyViewModelObject" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.mypath.MyCustomView
            android:id="@+id/my_view"
            app:myViewModel="@{myViewModel}"
            android:layout_width="match_parent"
            android:layout_height="40dp"/>

    </LinearLayout>
</layout>

In the above, an automatic binding attribute is created for app:myViewModel because there is a setter with the name setMyViewModel.