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?
View binding doesn't support layout variables or layout expressions, so it can't be used to declare dynamic UI content straight from XML layout files. View binding doesn't support two-way data binding.
View Binding is one of the best features which provides the views to bind with the activity which is ongoing. Replacing the findViewById() method, hence reducing the boilerplate code, generated the instances of the views of the current layout.
A well-designed custom view is much like any other well-designed class. It encapsulates a specific set of functionality with an easy to use interface, it uses CPU and memory efficiently, and so on. In addition to being a well-designed class, though, a custom view should: Conform to Android standards.
Using data binding can lead to faster development times, faster execution times and more readable and maintained code. Android data binding generates binding classes at compile time for layouts.
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.
First, don't do this if this custom view is already being <include>
in another layout, such as activity etc. You'll just get an exception about the tag being unexpected value. The data binding already ran the binding on it, so you're set.
Did you try using onFinishInflate
to run the bind? (Kotlin example)
override fun onFinishInflate() { super.onFinishInflate() this.dataBinding = MyCustomBinding.bind(this) }
Keep in mind that if you use the binding in your view, it won't be able to be created programmatically, at least it would be very convoluted to support both even if you can.
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