Reputation: 2113
View Binding got released as part of Android Jetpack
Docs: https://developer.android.com/topic/libraries/view-binding
My question is, how to use view binding with custom views. Google documentation has only show-cased Activity and fragment.
I tried this, but nothing was shown.
LayoutInflater inflater = LayoutInflater.from(getContext());
And then, I used this one, but again, no luck.
LayoutInflater inflater = (LayoutInflater)
getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
I guess maybe I don't target the correct layout inflater for my view but not sure.
Upvotes: 119
Views: 78610
Reputation: 37404
To use the view binding, you need to use the generated binding class not the LayoutInflater
, for example, if the layout name is result_profile.xml
then you need to use ResultProfileBinding
as:
class CustomView @kotlin.jvm.JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private var binding: ResultProfileBinding
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context))
addView(binding.root)
}
}
Auto generated class : result_profile.xml
-> ResultProfileBinding
(name of layout, appended with Binding
)
Inflate the binding
ResultProfileBinding.inflate(LayoutInflater.from(context))
Use addView
to add the view in the hierarchy as:
addView(binding.root)
Note: If you are extending from ConstraintLayout
(is the parent class) then use constraint set
Upvotes: 41
Reputation: 41
You can use DataBindingUtil
binding = DataBindingUtil.inflate(
LayoutInflater.from(context),
R.layout.your_layout_id,
this,
true
)
Upvotes: 1
Reputation: 17083
Just inform the root, and whether you want to attach to it
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context), this)
}
or
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context), this, true)
}
which inflate method to use will depend on the root layout type in xml.
Upvotes: 194
Reputation: 9625
You can initialize the view binding property right away
private val binding = CustomViewBinding.inflate(LayoutInflater.from(context), this)
Upvotes: 15
Reputation: 12826
This is the simplest kotlin answer I can think of. It's a custom view that just wraps a single TextView and provides an update(s:String)
function to update the text.
<!-- view_stub.xml -->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/myTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</layout>
// StubView.kt
class StubView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context,attrs,defStyleAttr) {
val binding = ViewStubBinding.inflate(context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
.also { addView(it.root) }
fun update(updatedText: String) {
binding.myTextView.text = updatedText
}
}
The two things I like about this answer are:
binding
is a val
instead of a var
. I try to limit the number of var
s as much as possible.addView
is closely associated with the val binding
using the also {}
scope function instead of an init {}
clause, making the instantiation of the View
feel much more declarative.One could argue that the addView()
is really a side effect and should be in the init {}
section so that it is separate from the declaration of the binding
val. I would argue the opposite -- declaring a val
then feeding it to a section of code that needs it does not feel like a side effect to me.
Upvotes: 2
Reputation: 990
If you are trying to use View Binding with the root view, this is working for me:
class CustomView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
private lateinit var binding: CustomViewBinding
override fun onFinishInflate() {
super.onFinishInflate()
binding = CustomViewBinding.bind(this)
}
}
Upvotes: 10