Add custom view to LinearLayout Dynamically using data binding(MVVM) - android

How can custom layout be added in LinearLayout if you are using data binding?
Here is my activity layout.
I want to add multiple layouts dynamically to "layoutOptions" linearLayout.
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/tools">
<data>
<variable
name="mainViewModel"
type="com.mihir.facilities.viewmodel.FacilitiesViewModel" />
</data>
<LinearLayout
android:id="#+id/layoutOptions"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</layout>
In my viewModel, I have inflated the layout I want to add, but I'm not sure how can I access "layoutOptions" linearLayout in my "FacilitiesViewModel" to call "addView" method.

Related

How inflate a Linear layout with custom view by databinding

I just want to make a map with some Vertical LinearLayout that in each of that have a Horizontal LinearLayout and in each of this layout wanna inflate a view that is like below code :
each_cell.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="live" type="Integer" />
<variable name="i" type="Integer" />
<variable name="j" type="Integer" />
</data>
<ImageView
android:id="#+id/itemView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
app:setI="#{i}"
app:setJ="#{j}"/>
each_row.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/row_instance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:orientation="horizontal">
</LinearLayout>
that I will add this Horizontal LL view to my main Vertical LL and the map will created
and kotlin code :
val cell = DataBindingUtil.inflate<EachCellBinding>(inflater , R.layout.each_cell , HorizontalLinearLayout.row_instance , true )
but the error is :
Required DataBindingComponent is null in class EachCellBindingImpl. A BindingAdapter in com.example.gameoflife.SartFragment.StartFragment is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.
As shown in the error you have declared the binding adapter methods in com.example.gameoflife.SartFragment.StartFragment. Declaring it inside a class makes it non-static. But the binding adapter methods should be always static. So take the methods from inside the class and put it outside the class and it will become static and your error will be resolved.

How to initialise click listener on Recycler view adapter using Databinding?

I am going to make an universal adapter for all dynamic layouts , normally i handled all this things but i got stuck that how to initialise click listener using interface so that i define in whatever xml and get event in my class.
i am following this link:
https://developer.android.com/topic/libraries/data-binding/index.html
suppose this is my root xml of recycler view:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="handlers" type="com.example.MyHandlers"/>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.firstName}"
android:onClick="#{handlers::onClickFriend}"
//>>> i want to initialise interface for position/view instead of #{handlers::onClickFriend}.
/>
</LinearLayout>
</layout>
Please give me link and solution , i will be thankful to you.
You can pass either user/position. If you want to pass position inside clickListener you must have to pass it as variable in xml same as user, and then
android:onClick="#{() -> handlers.onClickFriend(user)}
Or
<variable name="position" type="Integer"/>
and then
android:onClick="#{() -> handlers.onClickFriend(position)}

Breaking down complex XML layouts using the same data-binding context

Context
XML layouts in Android can get complicated. Hence, it is a good practice to break them down into conceptually independent modules. Consider the following example:
Main layout:
<layout>
<data>
<variable name="someVar" type="some.custom.Type"/>
</data>
<SomeLayout
...
android:someAttribute="#{someVar.someProperty}" />
<include layout="#layout/some_other_layout />
</layout>
and some_other_layout.xml:
<SomeOtherLayout
...
android:someOtherAttribute="#{someVar.someOtherProperty}" />
Problem
Is it possible to use the same data-binding context (whatever is inside <data>) in two separated layouts (like in the given example)?
Doing this naively results in java.lang.IllegalStateException.
From the Data Binding Library documentation:
Variables may be passed into an included layout's binding from the containing layout by using the application namespace and the variable name in an attribute:
<?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="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/name"
bind:user="#{user}"/>
<include layout="#layout/contact"
bind:user="#{user}"/>
</LinearLayout>
</layout>

Android Data Binding: Why doesn't passing in variable to ViewStubs work like include layouts?

With Android data binding it is possible to set a variable on a an included layout like so (from the documentation):
<?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="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/name"
bind:user="#{user}"/>
<include layout="#layout/contact"
bind:user="#{user}"/>
</LinearLayout>
</layout>
I've tried doing the same thing to pass in variables when using a ViewStub, but it doesn't work. Why don't ViewStubs work like include layouts?
Passing data to ViewStubs is working as expected. You define your namespace and pass the variable in that namespace, and accept it as a regular <variable> in your ViewStub layout, as follows:
main_layout.xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:my-namespace="http://schemas.android.com/apk/res-auto">
<data>
<variable name="myData" type="com.example.SomeModel" />
</data>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ViewStub
android:id="#+id/view_stub"
android:inflatedId="#+id/view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout="#layout/another_layout"
my-namespace:data="#{myData}"
/>
</RelativeLayout>
</layout>
another_layout.xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<!-- No need to declare my-namespace here -->
<data>
<variable name="data" type="com.example.SomeModel" />
</data>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{data.someValue}" />
</RelativeLayout>
</layout>
ViewStubs are called out as being different in the Data Binding Library documentation.
ViewStubs
ViewStubs are a little different from normal Views. They start off invisible and when they either are made visible or are explicitly told to inflate, they replace themselves in the layout by inflating another layout.
Because the ViewStub essentially disappears from the View hierarchy, the View in the binding object must also disappear to allow collection. Because the Views are final, a ViewStubProxy object takes the place of the ViewStub, giving the developer access to the ViewStub when it exists and also access to the inflated View hierarchy when the ViewStub has been inflated.
When inflating another layout, a binding must be established for the new layout. Therefore, the ViewStubProxy must listen to the ViewStub's ViewStub.OnInflateListener and establish the binding at that time. Since only one can exist, the ViewStubProxy allows the developer to set an OnInflateListener on it that it will call after establishing the binding.

Inflate a Viewstub that contains a Data Binding

I have an abstract BaseActivity class with this layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize" />
<ViewStub
android:id="#+id/activity_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
All activities in the app extends BaseActivity and overrides a method called getLayoutResID to provide its layout resource id which is inflated in the ViewStub. I do this to avoid having the Toolbar in each layout. The code in the base class that is used to inflate the layout is this:
private void setupLayout() {
setContentView(R.layout.activity_base);
ViewStub viewStub = (ViewStub) findViewById(R.id.activity_layout);
viewStub.setLayoutResource(getLayoutResID());
viewStub.inflate();
}
One of my activities use the new Data Binding system, below its layout:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.myapp.User" />
</data>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#{user.name}" />
</layout>
Although the data binding works perfectly the problem is that the ToolBar is not visible. Any idea why the data binding engine removes/hides the toolbar in this activity?
ViewStubs requires special attention as they replace themselves when being inflated, rather than populating themselves.
Read more on data-binding/guide#viewstubs
Another solution (to avoid ViewStub altogether) is to let your ConcreteActivities include a toolbar layout in their layout - instead of inflating a stub containing the toolbar. You'll also have less headache if you ever want to use custom a toolbar for an activity.

Categories

Resources