How inflate a Linear layout with custom view by databinding - android

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.

Related

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

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.

Why Isn't My Bound Data Showing Up in Android XML?

I have a custom layout that I want to reuse in several places, so I want to be able to pass a title to it, since that's the only value that will actually change. I know I can do that by binding data, but I can't get the data to render.
In my activity.main I have:
<?xml version="1.0" encoding="utf-8"?>
<layout 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" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.r.e.MainActivity">
<include
layout="#layout/switch_preference_custom_title"
app:passedTitle="#{#string/hello_world}" />
</RelativeLayout>
</layout>
I have defined my custom layout as follows:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >
<data>
<variable
name="passedTitle"
type="String"/>
</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="#{passedTitle}" />
</RelativeLayout>
</layout>
I also added
dataBinding {
enabled = true
}
in my build.gradle. My project compiles and runs fine, and the layout does render (I can tell by giving it a background), but the text is an empty string.
It looks like one final linking piece was missing. Instead of having
setContentView(R.layout.activity_main);
in MainActivity, one needs to declare
DataBindingUtil.setContentView(this, R.layout.activity_main);
This connects the Data Binding library with the root layout, without which none of your data bindings will actually render.

Android - Make new view attribute and pass to its children in XML compound view component - data binding in layout

Full answer:
1. Enable data binding in app/build.gradle:
dataBinding {
enabled true
}
2. Use DataBindingUtil to set content view
java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DataBindingUtil.setContentView(this, R.layout.activity_engineering_mode_main);
}
3. Child item layout
You will see that I define 2 new attributes
values/bools.xml
<variable
name="textTitle"
type="String" />
<variable
name="buttonVisibility"
type="boolean" />
With textTitle, you can use any string from resource by #string/string_name
With buttonVisibility, you have to define bool resource type, and use #bool/bool_name
layout/item_engineering_list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.view.View" />
<variable
name="textTitle"
type="String" />
<variable
name="buttonVisibility"
type="boolean" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="#dimen/engineer_actionbar_height"
android:background="#color/engineer_background_color"
android:orientation="horizontal">
<TextView
android:id="#+id/engineer_txtName"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="#dimen/engineer_text_margin"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="#{textTitle}"
android:textColor="#color/engineer_text_color"
android:textSize="#dimen/engineer_title_font_size" />
<Button
android:id="#+id/engineer_btnNext"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="#dimen/engineer_text_margin"
android:text="BACK"
android:visibility="#{buttonVisibility ? View.VISIBLE : View.GONE, default=gone}" />
</LinearLayout>
</layout>
4. Boolean resource file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="item_button_visibility_default">false</bool>
<bool name="item_button_visibility_on">true</bool>
<bool name="item_button_visibility_off">false</bool>
</resources>
5. Parent layout, which includes some children and passes value to new attributes
<?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
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/includedLayout0"
layout="#layout/item_engineering_list_row"
app:buttonVisibility="#{#bool/item_button_visibility_on}"
app:textTitle="#{#string/app_name}" />
<include
android:id="#+id/includedLayout1"
layout="#layout/item_engineering_list_row"
app:buttonVisibility="#{#bool/item_button_visibility_default}"
app:textTitle="#{#string/app_name}" />
</LinearLayout>
</layout>
Original Question:
I am new to android and I've been working with QML in QT for a time.
I wonder how I can make a layout more easier by applying params in XML in compound view components.
I have a custom layout item in xml and want to pass some attributes from a parent to its children, and I also want to initialize parent's attribute with new values to customize its children too.
My concept is as below:
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
!!!! how to declare a new attribute here !!!
| like this:
| textTitle="New Title" // default value for child
| buttonVisibility="visible" // default value for child
">
<TextView
android:id="#+id/engineer_txtTitle"
android:text= textTitle <--- use parent's />
<Button
android:id="#+id/engineer_btnBack"
android:visibility= buttonVisibility <== use parent's />
</LinearLayout>
CLICK HERE TO SEE IMAGE: base Item
main.xml
<LinearLayout>
<include
android:id="#+id/item1"
layout="#layout/item"
textTitle= "FIRST"
// buttonVisibility not set here, use default as visible
/>
<include
android:id="#+id/item2"
layout="#layout/item"
textTitle= "SECOND"
buttonVisibility = "gone" // dont show button
/>
</LinearLayout>
CLICK HERE TO SEE IMAGE: apply with param
You can use Data Binding of Architecture component. Here is an sample of your requirement.
Recently I answered a question related to this.
Clean answer
This example shows pass value to <include.
I have a common view layout_common.xml, I want to pass String to included layout. I will create a variable of type String. Refer that String to your TextView. I created passedText for example.
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
>
<data>
// declare fields
<variable
name="passedText"
type="String"/>
</data>
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{passedText}"/> //set field to your view.
</layout>
Now you can pass passedText field 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
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<include
android:id="#+id/includedLayout"
layout="#layout/layout_common"
app:passedText="#{#string/app_name}" // here we pass any String
/>
</LinearLayout>
</layout>
Note that both layouts (parent & included) should be binding layout, i.e. wrapped with <layout> and </layout> tags
Thanks #Khemraj to show the keyword "Data Binding" in Android :)
I have found the answer for me. It includes Khemraj's answer and some small code added to values resource.
I posted it in my question for others to find it easily.

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)}

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.

Categories

Resources