View Binding - How to Get a Binding for Included Layouts

View Binding - How do I get a binding for included layouts?

In case of:

  1. Include with generic layout (not merge node), we need to assign ID to included part, this way in binding we will have access to included sub part
<include
android:id="@+id/your_id"
layout="@layout/some_layout" />

This way in your activity code:

private lateinit var exampleBinding: ActivityExampleBinding  //activity_example.xml layout

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
exampleBinding = ActivityExampleBinding.inflate(layoutInflater)
setContentView(exampleBinding.root)
//we will be able to access included layouts view like this
val includedView: View = exampleBinding.yourId.idOfIncludedView
//[...]
}

  1. Include with merge block in external layout. We can't add ID to it because merge block is not a view.
    Let's say we have such eternal merge layout (merge_layout.xm):
<?xml version="1.0" encoding="utf-8"?>
<merge 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/activity_example">

<TextView
android:id="@+id/some_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World" />
</merge>

To properly bind such merge layout we need to:

In your activity code:

private lateinit var exampleBinding: ActivityExampleBinding  //activity_example.xml layout
private lateinit var mergeBinding: MergeLayoutBinding //merge_layout.xml layout

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
exampleBinding = ActivityExampleBinding.inflate(layoutInflater)
//we need to bind the root layout with our binder for external layout
mergeBinding = MergeLayoutBinding.bind(exampleBinding.root)
setContentView(exampleBinding.root)
//we will be able to access included in merge layout views like this
val mergedView: View = mergeBinding.someView
//[...]
}

How to use View Binding with Included Views?

Let's suppose that the layout in your question is activity_main.xml. The generated view binding class for it is ActivityMainBinding. Similarly, for item_header.xml, the generated view binding is ItemHeaderBinding.

If we pretend that item_header.xml has a TextView named @+id/foo, then you wind up with this chunk of Kotlin:

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val mainBinding = ActivityMainBinding.inflate(layoutInflater)

setContentView(mainBinding.root)

mainBinding.myHeader.foo.text = "this is a test"
}
}

So, the ActivityMainBinding object should have a property with the android:id that you gave to the <include>myHeader in this case. That should be an ItemHeaderBinding, as view binding appears to set up the nested binding object for the <include>. Since myHeader is an ItemHeaderBinding, you can then reference widgets on it just as you would if you directly inflated ItemHeaderBinding yourself.

Note that view binding appears to convert lower_snake_case into lowerCamelCase, so the my_header ID turns into myHeader in terms of the generated code.

View binding with include layout not working

I do nothing on it and it just works automatically. I surely did clean, rebuild, restart Android studio... something at that time but not working. Maybe link another layout in another class would trigger something just fix it under the hood cause I set aside this problem and keep going.

ViewBinding - Included Layout Binding Resulting in Unresolved Reference

If you're using Android Studio 3.6.0 sometimes gradle plugin fails to generate ViewBinding fields for included layouts. Please update to Android Studio 3.6.1 and gradle plugin version to 3.6.1.

How to use View Binding with Included Views in Java?

I have resolved the problem.

Original item_header.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
android:background="@android:color/transparent">
<TextView
android:id="@+id/foo"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>

I removed id of framelayout and the error was soon gone.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
android:background="@android:color/transparent">
<TextView
android:id="@+id/foo"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>

Be careful about using id while using view binding.

How to include an Android layout but also access its elements in binding?

Two things are required in order to use ViewBinding with an included layout.

<merge> is not supported

The documentation only covers Data Binding, and not View Binding, but it does appear to be applicable to both. See https://developer.android.com/topic/libraries/data-binding/expressions#includes

Data binding doesn't support include as a direct child of a merge element.

In other words, the layout must have a real, concrete view as its root element. The following is supported:

<LinearLayout ...>
<TextView ... />
<TextView ... />
</LinearLayout>

But a layout with a <merge> root is not supported:

<merge ...>
<TextView ... />
<TextView ... />
</merge>

The <include> tag must specify an ID

It is, in general, possible to include a layout without explicitly specifying an ID. View Binding does not support this:

<include layout="@layout/included_layout"/>

Even if the included layout has an ID on its root element, it is still not supported. Instead, you must explicitly specify the ID on the <include> tag:

<include
android:id="@+id/some_id"
layout="@layout/included_layout"/>

Once both of these conditions are satisfied, your generated binding for the outer layout will include a reference to the binding of the included layout. Let's say our two files are outer_layout.xml and included_layout.xml. Then these two files would be generated:

  • OuterLayoutBinding.java
  • IncludedLayoutBinding.java

And you could reference the included views like this:

val outerBinding = OuterLayoutBinding.inflate(layoutInflater)
val innerBinding = binding.someId // uses the id specified on the include tag
val innerView = innerBinding.viewPagerTop

Or, for short:

val binding = OuterLayoutBinding.inflate(layoutInflater)
val innerView = binding.someId.viewPagerTop

ViewBinding - How to set visibility for include layout in ViewBinding?

When we give <include> an id it overrides the id of root layout that we included. In your case, layout_provinces is overriding <RelativeLayout's select_province. So when you access the relative layout it gives you an error because it is no longer there.

What you can do is remove the id of relative layout and only give id to include and access the root layout that you included through the getRoot() method like below.

Java

binding.selectProvince.getRoot().setVisibility(View.GONE)

Kotlin

binding.selectProvince.root.visibility = View.GONE

the getRoot() method in View Binding returns the topmost view of the given layout in your case it's the RelativeLayout.

DataBindingUtil bind layout from include

To use DataBinding in for fragment in android, use following way->

Create ->

private FragmentYourVideosBinding binding;
private View view;

Then use - >

binding = DataBindingUtil.inflate(inflater, R.layout.fragment_your_videos, container, false);
view = binding.getRoot();
return view;

To access the FragmentBindinding just type FragmentBinding then you will see your Fragment Binding layout name in dropdownlist. Is described in above link you can read from there.

Firstly wrap your all child layouts by layout tag as below. You can copy the code its same as your code.

            <?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:bind="http://schemas.android.com/tools" >

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<view.TouchyWebView
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="@+id/content_view" >
</view.TouchyWebView>

<include
android:id="@+id/view_list"
layout="@layout/fragment_list"
android:layout_width="match_parent"
android:layout_height="596dp"
app:layout_constraintTop_toBottomOf="@+id/content_view"
tools:layout_editor_absoluteX="-9dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

</layout>


Related Topics



Leave a reply



Submit