I have a layout as such:
<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="viewModel"
type="com.myPackage.MyViewModel" />
</data>
<android.support.design.widget.CoordinatorLayout>
<include layout="#layout/modal_popup_view" />
</android.support.design.widget.CoordinatorLayout>
</layout>
How can I pass the variable viewModel into the included layout?
Define a viewModel (or any other named) variable in your #layout/modal_popup_view.
<data>
<variable
name="viewModel"
type="com.myPackage.PopupViewModel" />
</data>
In MyViewModel, expose the property popupViewModel of the type PopupViewModel. Pass the property to the included layout.
<include layout="#layout/modal_popup_view"
app:viewModel="#{viewModel.popupViewModel}" />
Related
I am having some issues with data binding a #string/title into a include tag.
relevant include xml
<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>
<import type="kotlin.jvm.functions.Function0"/>
<variable
name="saveVisibility"
type="Boolean" />
<variable
name="closeClick"
type="Function0<kotlin.Unit>" />
<variable
name="titleText"
type="String" />
<variable
name="saveClick"
type="Function0<kotlin.Unit>" />
</data>
<TextView
android:id="#+id/toolbarTitle"
style="#style/HeadlineSecondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/margin_normal"
android:layout_marginEnd="#dimen/margin_normal"
android:text="#{titleText}"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/toolbarSave"
app:layout_constraintStart_toEndOf="#id/toolbarClose"
app:layout_constraintTop_toTopOf="parent"
tools:text="#string/toolbar_title_placeholder" />
As you can see I have a variable called titleText and I am basically just trying to set a textview using it.
Here is the parent XML that is not working for this titleText
<include
android:id="#+id/toolbar"
layout="#layout/toolbar_close_save_databind"
app:titleText="#string/title"
app:saveVisibility="#{viewModel.isModified}"
app:saveClick="#{viewModel::saveData}"
app:closeClick="#{viewModel::closeClick}" />
I am not sure why it can't link the string into the include tag.
I am using livedata and databinding in my project. And whenever i fetch data from webservices, i am databinding it with livedata. I can pass livedata object to first viewStub from root layout. It observes livedata as expected. But i am trying to pass this liveData to second viewStub which is placed in first viewStub. But it is not observing livedata when livedata's value changes.
root layout which is contains first viewStub:
<data>
<import type="android.view.View" />
<import type="android.text.TextUtils" />
<variable
name="viewModel"
type="com.test.test.MyViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ViewStub
android:id="#+id/stub_import"
android:inflatedId="#+id/panel_import"
android:layout_width="match_parent"
android:layout_height="wrap_content"
bind:viewModel="#{viewModel}" />
</RelativeLayout>
first viewStub layout which is contains second viewStub:
<data>
<import type="android.view.View" />
<import type="android.text.TextUtils" />
<variable
name="viewModel"
type="com.test.test.MyViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
.
.
.
.
<ViewStub
android:id="#+id/second_stub_import"
android:inflatedId="#+id/second_panel_import"
android:layout_width="match_parent"
android:layout_height="wrap_content"
bind:viewModel="#{viewModel}" />
.
.
.
.
</RelativeLayout>
And the second viewStub layout which is using liveData from passed viewModel:
<data>
<import type="android.view.View" />
<import type="android.text.TextUtils" />
<variable
name="viewModel"
type="com.test.test.MyViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{viewModel.textLiveData}"
android:textColor="#color/general_text_color"
android:textSize="18sp" />
</RelativeLayout>
And additionally i can replace second viewStub to "include tag". This would help as well but it is not observing either.
When a viewStub layout contains another viewStub or include tag, and passing some observable objects to these layouts. it won't observe.
Can anyone tell me any solution for this situation?
Is there a way to pass data variable to included layout?
parent layout
<?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"
tools:showIn="#layout/fragment_settings">
<data>
<variable
name="viewModel"
type="......settings.SettingsFragmentViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:overScrollMode="never"
android:padding="#dimen/spacing_default">
<include
android:id="#+id/main"
layout="#layout/layout_settings_main" />
</androidx.constraintlayout.widget.ConstraintLayout>
and want to have viewModel in included layout
<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"
tools:showIn="#layout/fragment_settings">
<data>
<variable
name="viewModel"
type="......settings.SettingsFragmentViewModel" />
</data>
<merge>
...........
or is it possible only when setting like this:
binding = FragmentSettingsBinding.inflate(inflater, container, false).apply {
lifecycleOwner = this#SettingsFragment
viewModel = this#SettingsFragment.viewModel
main.viewModel = this#SettingsFragment.viewModel
}
In parent xml inside include tag pass data variable to included layout using bind:viewModel.
<?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"
xmlns:bind="http://schemas.android.com/apk/res-auto"
tools:showIn="#layout/fragment_settings">
<data>
<variable
name="viewModel"
type="......settings.SettingsFragmentViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:overScrollMode="never"
android:padding="#dimen/spacing_default">
<include
android:id="#+id/main"
layout="#layout/layout_settings_main"
bind:viewModel="#{viewModel}" />
</androidx.constraintlayout.widget.ConstraintLayout>
Your included layout will get object instance in viewModel.
For more details check this tutorial
Open build.grade and add dataBinding { enabled = true } in block android{ // ...}
Ok so, at the beginning of this article I’ve said that it depends whether it’s possible to pass the variable to a secondary layout or not. The reason for this is the following:
Data binding does not support include as a direct child of a merge element. For example, the following layout is not supported:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<variable name="user" type="it.communikein.myunimib.User"/>
</data>
<merge>
<include layout="#layout/name"
bind:user="#{user}"/>
<include layout="#layout/contact"
bind:user="#{user}"/>
</merge>
</layout>
while integrating the BottomSheet we need to make the parent layout as the CoordinatorLayout but in databinding we use <layout>. While implementing this it throws an exception :-
Caused by: java.lang.IllegalArgumentException: The view is not a child of CoordinatorLayout.
How to integrate BottomSheet with databinding
<layout>
<data>
<import type="android.view.View" />
<variable
name="cabLayoutBinder"
type="newage.com.hopin.rideBooking.CabSelectActivity" />
<variable
name="modelBinder"
type="newage.com.hopin.rideBooking.model.DataBinders" />
<variable
name="fareSetters"
type="newage.com.hopin.rideBooking.model.FareDetails" />
</data>
<android.support.design.widget.CoordinatorLayout
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"
tools:context=".rideBooking.CabSelectActivity">
</android.support.design.widget.CoordinatorLayout>
</layout>
You put context in your coordinator, but in databinding you don't implement this way.
Try to remove this line and try again:
tools:context=".rideBooking.CabSelectActivity"
Let me know if it worked.
This is how I am using it
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".com.abc.Activity">
<data>
<variable
name="viewModel"
type=".com.abc.ViewModel" />
</data>
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
layout="#layout/toolbar" />
</FrameLayout>
<!-- Adding bottom sheet after main content -->
<include layout="#layout/bottom_sheet" />
</android.support.design.widget.CoordinatorLayout>
</layout>
I tried to use the me.tatarka.bindingcollectionadapter:bindingcollectionadapter library after I added it to gradle :
compile 'me.tatarka.bindingcollectionadapter:bindingcollectionadapter:1.3.0'
compile 'me.tatarka.bindingcollectionadapter:bindingcollectionadapter-recyclerview:1.3.0'
I used it in the xml file like this:
<layout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
>
<data>
<variable name="viewModel" type="com.example.ViewModel"/>
<import type="me.tatarka.bindingcollectionadapter.LayoutManagers" />
</data>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toStartOf="#+id/recycler"
app:layoutManager="#{LayoutManagers.linear()}"
app:items="#{viewModel.items}"
app:itemView="#{viewModel.itemView}"/>
</RelativeLayout>
</layout>
Identifiers must have user defined types from the XML file. LayoutManagers is missing it file
****\ data binding error ****
Could someone help me?
Thanks.
Data must be a children of layout
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable name="viewModel" type="com.example.ViewModel"/>
<import type="me.tatarka.bindingcollectionadapter.LayoutManagers" />
</data>
<!-- Rest of your layout -->
</layout>