The Android documentation does a great job of describing how one can create a binding class using a layout xml file. But I have a couple of questions.
Is there a way to create a data binding class for a custom view that is instantiated programmatically? For example, lets say I have two custom view classes and I want to bind the same view model object to them programmatically without using any xml. The classes are as follows:
class MyViewModel {
}
class MyCustomView extends View {
}
class MyAnotherCustomView extends MyCustomView {
}
Now lets say I instantiate MyCustomView/MyAnotherCustomView using:
MyCustomView customView = new MyCustomView(context);
How do I go about using data binding in this case? Is this possible using the official Android data binding framework? If not, what other frameworks/libraries are available or recommended to achieve this?
My second question is a follow up of the first question. Lets say it is not possible to achieve what I want in my first question. Then, I will have to define a my_custom_view.xml
file. This will look something like this:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User"/>
</data>
<com.example.name.MyCustomView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@{user.firstName}"/>
</layout>
Now, if I want to use MyAnotherCustomView which is a subclass of MyCustomView keeping the binding logic the same, will I have to create a new xml file my_another_custom_view.xml
just to replace MyCustomView with MyAnotherCustomView to define the same binding?
The answer to the first question is "No." Android data binding requires the XML to generate the binding classes.
In your second question, you offer a solution that will work. If you go that route, one way to do it is to use the ViewDataBinding base class setters to set your variables. I can imagine a method like this:
public void addCustomView(LayoutInflater inflater, ViewGroup container, User user) {
ViewDataBinding binding = DataBindingUtil.inflate(inflater,
this.layoutId, container, true);
binding.setVariable(BR.user, user);
}
Here, I've assumed the selection of which custom View is determined by a field layoutId
. Each possible layout will have to define a user
variable of type User
.
I don't know the particulars of your use, but if you want to dynamically choose which custom view to load, you could use a ViewStub. You could also do the same thing with just visibility if you don't have any tremendous overhead in loading your custom Views.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View"/>
<variable name="user" type="com.example.User"/>
<variable name="viewChoice" type="int"/>
</data>
<FrameLayout ...>
<!-- All of your outer layout, which may include binding
to the user variable -->
<ViewStub android:layout="@layout/myCustomView1"
app:user="@{user}"
android:visiblity="@{viewChoice == 1} ? View.VISIBLE : View.GONE"/>
<ViewStub android:layout="@layout/myCustomView2"
app:user="@{user}"
android:visiblity="@{viewChoice == 2} ? View.VISIBLE : View.GONE"/>
</FrameLayout>
</layout>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With