Android Data Binding using include tag
Solution 1
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
Easy Complete Example
Just set
id
to included layout, and usebinding.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
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
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
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)
Related videos on Youtube
Comments
-
Kamil Nękanowicz over 2 years
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?
-
Andrew Hossam over 3 years
-
-
George Mount over 8 years1.0-rc4 now fixes the problem of needing the unnecessary variable. You can now use simply:
<include layout="@layout/buttons" android:id="@+id/buttons"/>
. You still need the id so that it will produce a public field for you so that you can access the Button View. -
Nilzor over 8 yearsAre anyone else having problems binding click events on the layout though?
-
George Mount over 8 yearsAre you using data binding syntax?
android:onClick="@{myObj.clickHandler}"
-
Sowmia Sundararajan almost 8 yearsDatabinding with include support. developer.android.com/topic/libraries/data-binding/…
-
Rishabh876 over 6 yearsMain point to remember here is to get the button reference, you need to do
binding.{id of include tag}.button
instead ofbinding.button
. Took me a while to figure it out. -
Khemraj Sharma almost 6 years@GeorgeMount How to call static method from layout element like
android:text="{MyClass.getUser().name}"
? -
George Mount almost 6 yearsYou can do that either by importing the class name using the
<import type="com.example.MyClass"/>
in thedata
section or by using the fully qualified class name in the expression:android:text="@{com.example.MyClass.user.name}"
-
CodingTT over 5 yearswhat if you want to pass in two parameters/
-
George Mount over 5 yearsIf you want to pass two parameters, you can just do that.
<include layout="..." app:param1="@{1}" app:param2="@{2}"/>
whereparam1
andparam2
are variables in your included layout. -
Neon Warge over 5 yearsApologies, would you care to type the entire layout? This '...' all over the place is pretty much unreadable. Like I don't understand if I still include <merge> tag?
-
Ewan over 5 years@NeonWarge There is a complete example at developer.android.com/topic/libraries/data-binding/…. It adds "Data binding doesn't support include as a direct child of a merge element"
-
Daniel Carpio Contreras over 5 yearsI've got an error message that says: "Only one layout element and one data element are allowed"
-
iCantC over 5 yearsIn your answer you handled the setText event programmatically ,Instead of TextView if it would have been a Button , then how would you have handled its click event .I know that programmatically
binding.includedLayout.button.setOnClickListener
would be the alternative,but what if i want to useonClick
attribute in XML itself ? -
Khemraj Sharma over 5 yearsYou can pass
OnClickListener
to included layout. even you can pass anything in binding. Check this answer, if you need more help, let me know. stackoverflow.com/a/51722829/6891563 -
Elliptica about 5 yearsWhen I do this, I just get a blank field for
passedText
. The only difference is I don't include the MainActivity code because I just want to pass the string resource in <include> and leave it like that. Why is it always blank though? -
Martin Rajniak about 4 years@GeorgeMount it doesn't work for me with "app" namespace. It has to be "bind" namespace for it to generate correct code. Like this:
bind:foo={something}
-
M. Wojcik over 3 years@Elliptica As its databinding, I guess the value for
passedText
should be anObservableField
or a LiveData, otherwise it will never be actually loaded, right @Khemraj? -
IgorGanapolsky over 3 yearsThis doesn't compile.
Error: cannot find symbol
-
the_prole about 3 yearsI had to clean/rebuild because I switched over from findViewById.
-
Patrick almost 3 yearsI have this error: attribute foo not found.