Search code examples
androiddata-bindingcustom-view

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?


Solution

  • 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.