Android Data Binding using include tag
JavaAndroidData BindingAndroid ButtonAndroid DatabindingJava Problem Overview
Update note:
The above example works properly, because release 1.0-rc4 fixed the issue of needing the unnecessary variable.
Original question:
I do exactly as it is described in the documentation and it does not work:
main.xml:
<layout xmlns:andr...
<data>
</data>
<include layout="@layout/buttons"></include>
....
buttons.xml:
<layout xmlns:andr...>
<data>
</data>
<Button
android:id="@+id/button"
...." />
MyActivity.java:
... binding = DataBindingUtil.inflate...
binding.button; ->cannot resolve symbol 'button'
how to get button?
Java Solutions
Solution 1 - Java
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"/>
....
Solution 2 - Java
###Easy Complete Example
> Just set id
to included layout, and use binding.includedLayout.anyView
.
This example helps passing a value to <include
& accessing included views in code.
###Step 1
You have layout_common.xml
, want to pass String
to included layout.
You will create String
variable in layout and refer this String
to TextView
.
<data>
// declare fields
<variable
name="passedText"
type="String"/>
</data>
<TextView
android:id="@+id/textView"
...
android:text="@{passedText}"/> //set field to your view.
###Step 2
Include this layout to parent layout. Give an id
to included layout, so that we can use that in binding class. Now you can pass String passedText
to your <include
tag.
activity_main.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/layout_common"
app:passedText="@{@string/app_name}" // here we pass any String
/>
</LinearLayout>
</layout>
-
You can use now
binding.includedLayout.textView
in your class. -
You can pass any variables to included layout like above.
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.includedLayout.textView.setText("text");
Note Both layouts (parent & included) should be binding layout
, wrapped with <layout
Solution 3 - Java
just set an id for your include layout
<include
android:id="@+id/layout"
layout="@layout/buttons" />
then
BUTTONSBINDING binding = yourMainBinding.layout;
BUTTONSBINDING
is res/layout/buttons.xml
now :
binding.button.setText("simple_Way");
Solution 4 - Java
You can make your bind work on your include just adding a ID to it like so:
<include
android:id="@+id/loading"
layout="@layout/loading_layout"
bind:booleanVisibility="@{viewModel.showLoading}" />
Solution 5 - Java
An other interesting thing on this is that you can pas variables to the imported layout from the binder like this:
MainBinding binding = MainBinding.inflate(getLayoutInflater());
binding.buttons.setVariable(BR.varID, variable)
Solution 6 - Java
it seems you have empty data tag in your xml file please cross check, it is making cause to not generate include layout file
<data>
</data>
remove this tag if your not using, will solve the problem
Solution 7 - Java
I would like to add, I had the similar problem. My problem was that the variable name was title, the same as id name. There was no compile error. (Not 100% sure was that a problem, I also clean the project)
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="title"
type="String" />
</data>
...
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/title"...>
<androidx.appcompat.widget.AppCompatTextView>
...
</layout>
Solution 8 - Java
Just you make sure your include layout has enabled dataBinding tag
below code is my layout that I include in other layout
<data>
<variable
name="backBinding"
type="String" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cl_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen_30"
android:layout_marginTop="@dimen/dimen_30"
android:padding="@dimen/dimen_2"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:id="@+id/iv_back"
android:layout_width="@dimen/dimen_10"
android:layout_height="@dimen/dimen_20"
android:contentDescription="@string/back"
android:src="@drawable/ic_back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_back"
style="@style/AidoFTTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen_10"
android:text="@string/face_training"
android:textSize="@dimen/text_20"
app:layout_constraintBottom_toBottomOf="@id/iv_back"
app:layout_constraintStart_toEndOf="@id/iv_back"
app:layout_constraintTop_toTopOf="@id/iv_back" />
</androidx.constraintlayout.widget.ConstraintLayout>
here I am including in my main layout
<data>
<variable
name="viewModel"
type="com.ingenDynamic.coreaidokotlin.viewModels.VideoCallViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/aido_main_background"
tools:context=".ui.aidoVideoCall.ContactActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/back_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen_20"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_appBar">
<include
android:id="@+id/back"
layout="@layout/app_back_layout"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
and directly I can access my included layout
binding.backLayout.setOnClickListener { finish() }
binding.back.tvBack.text = getText(R.string.video_call)