Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android data binding is not working with <merge> attributes

I'm trying to use databinding with custom views (a possible usage George Mount showed here).

One can't imagine building compound views without <merge> tag. However, in this situation databinding fails:

MyCompoundView class:

public class MyCompoundView extends RelativeLayout {  MyCompoundViewBinding binding;  public MyCompoundView (Context context, AttributeSet attrs) {     super(context, attrs);     init(context); }  private void init(Context context){     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);     binding = MyCompoundViewBinding.inflate(inflater, this, true); } 

my_compound_view.xml: by app:isGone="@{!data.isViewVisible}" i hoped to control the visibility of the whole compound view

<?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>         <variable name="data" type="com.example.MyViewModel"/>     </data>      <merge         android:layout_width="wrap_content"         android:layout_height="wrap_content"         app:isGone="@{!data.isViewVisible}">          <ImageView             android:id="@+id/image_image"             android:layout_width="60dp"             android:layout_height="60dp"             app:imageUrl="@{data.imagePhotoUrl}"/>           <!-- tons of other views-->      </merge>  </layout> 

The compiler errors:

Error:(13) No resource identifier found for attribute 'isGone' in package 'com.example' Error:(17, 21) No resource type specified (at 'isGone' with value '@{!data.isViewVisible}'). 

I have all needed @BindingAdapter methods. Now I inherit the view from FrameLayout and use <RelativeLayout> instead of <merge> - and it works. But I have extra nested layout.

Question: merge attrs are ignored. Is there any way to workaround that?

Android Studio 1.5.1 stable

Gradle plugin com.android.tools.build:gradle:1.5.0

like image 465
Dmitry Gryazin Avatar asked Feb 23 '16 23:02

Dmitry Gryazin


People also ask

Can I use both databinding and ViewBinding?

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.

Is data binding deprecated Android?

Kotlin Android Extensions is deprecated, which means that using Kotlin synthetics for view binding is no longer supported.

Is data binding good in Android?

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.

What is merge tag in Android XML?

Use the <merge> tag For example, if your main layout is a vertical LinearLayout in which two consecutive views can be re-used in multiple layouts, then the re-usable layout in which you place the two views requires its own root view.


2 Answers

There is no merge object after inflation, so there is nothing to assign values to with a merge tag. I can't think of any binding tag that will work on merge.

You can assign the tag to the root element and use the BindingAdapter to do what you want.

<layout     xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     >      <data>         <variable name="data" type="com.example.MyViewModel"/>     </data>      <merge         android:layout_width="wrap_content"         android:layout_height="wrap_content">         <ImageView             app:isGone="@{!data.isViewVisible}"             android:id="@+id/image_image"             android:layout_width="60dp"             android:layout_height="60dp"             app:imageUrl="@{data.imagePhotoUrl}"/>          <!-- tons of other views-->     </merge> </layout> 

If you want to do something with the Binding class itself, you can use the DataBindingUtil to find the object from the View.

@BindingAdapter("isGone") public static void setGone(View view, boolean isGone) {     ViewDataBinding binding = DataBindingUtil.findBinding(view);     //... do what you want with the binding. } 
like image 178
George Mount Avatar answered Sep 19 '22 11:09

George Mount


Actually you can use <merge> tag inside <include> and do data binding.

Ex:

incl_button.xml

<layout>     <merge xmlns:android="http://schemas.android.com/apk/res/android">          <Button android:id="btn"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:text="Click"          />      </merge> </layout> 

fragment_example.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android">      <LinearLayout         android:layout_width="match_parent"         android:layout_height="match_parent">          <include             layout="@layout/incl_button"             android:id="@+id/layout_btn" />      </LinearLayout> </layout> 

ExampleFragment.kt

binding.layoutBtn.btn.setOnClickListener{    //... } 
like image 26
user158 Avatar answered Sep 20 '22 11:09

user158