Android Data Binding Using Include Tag

Android Data Binding using include tag

The problem is that the included layout isn't being thought of as a data-bound layout. To make it act as one, you need to pass a variable:

buttons.xml:

<layout xmlns:andr...>
<data>
<variable name="foo" type="int"/>
</data>
<Button
android:id="@+id/button"
... />

main.xml:

<layout xmlns:andr...
...
<include layout="@layout/buttons"
android:id="@+id/buttons"
app:foo="@{1}"/>
...

Then you can access buttons indirectly through the buttons field:

MainBinding binding = MainBinding.inflate(getLayoutInflater());
binding.buttons.button

As of 1.0-rc4 (just released), you no longer need the variable. You can simplify it to:

buttons.xml:

<layout xmlns:andr...>
<Button
android:id="@+id/button"
... />

main.xml:

<layout xmlns:andr...
...
<include layout="@layout/buttons"
android:id="@+id/buttons"/>
....

View Binding - How do I get a binding for included layouts?

In case of:

  1. Include with generic layout (not merge node), we need to assign ID to included part, this way in binding we will have access to included sub part
<include
android:id="@+id/your_id"
layout="@layout/some_layout" />

This way in your activity code:

private lateinit var exampleBinding: ActivityExampleBinding  //activity_example.xml layout

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
exampleBinding = ActivityExampleBinding.inflate(layoutInflater)
setContentView(exampleBinding.root)
//we will be able to access included layouts view like this
val includedView: View = exampleBinding.yourId.idOfIncludedView
//[...]
}

  1. Include with merge block in external layout. We can't add ID to it because merge block is not a view.
    Let's say we have such eternal merge layout (merge_layout.xm):
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="@layout/activity_example">

<TextView
android:id="@+id/some_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World" />
</merge>

To properly bind such merge layout we need to:

In your activity code:

private lateinit var exampleBinding: ActivityExampleBinding  //activity_example.xml layout
private lateinit var mergeBinding: MergeLayoutBinding //merge_layout.xml layout

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
exampleBinding = ActivityExampleBinding.inflate(layoutInflater)
//we need to bind the root layout with our binder for external layout
mergeBinding = MergeLayoutBinding.bind(exampleBinding.root)
setContentView(exampleBinding.root)
//we will be able to access included in merge layout views like this
val mergedView: View = mergeBinding.someView
//[...]
}

Include tag and dataBinding

You can pass that from parent.xml

<include layout="@layout/custom"
android:id="@+id/layout1"
app:user="@{object of user1`}"/>

<include layout="@layout/custom"
android:id="@+id/layout2"
app:user="@{object of user2`}"/>

Here you need to pass User object from parent.xml

Make sure you have <data> in custom.xml

<data>
<variable name="user" type="com.myproject.model.User"/>
</data>

Here is detailed answer related to this, refer it

Pass data to include layout using Databinding

It seems like you want to include a common layout and then pass dynamic parameters from the main layout to included layout, here are the steps,

Step 1: Enable DataBinding in your project

//In the build.gradle file in the app module, add this 

android {
...
dataBinding {
enabled = true
}
}

Step 2: Create your common_layout_included.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>

<data>
<variable
name="username"
type="String"/>
</data>

<LinearLayout
..
>

<TextView
android:id="@+id/tv_username"
android:text="@{username}"/>

</LinearLayout>

</layout>

Step 3: Include common_layout_included.xml in your main_layout.xml

<?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">

<LinearLayout
..
>

<include
android:id="@+id/includedLayout"
layout="@layout/common_layout_included"
app:username="@{@string/username}" // here we pass any String
/>

</LinearLayout>
</layout>

Step 4: Make sure you inflate the layout using DataBinding way

//In the onCreate of your Activity

val binding = DataBindingUtil.setContentView(this,R.layout.main_layout)

That's it, you are good to go. If still some error appears just do File -> Invalidate Caches/Restart

One last thing, I saw that you are assigning the id's to the view's dynamically android:id="@{edittext_id}", in all of my experience, I never really encountered a use case where I would be motivated to do this. I don't even know if it's possible and even if possible I doubt it's a good practice.



Related Topics



Leave a reply



Submit