如何在自定义视图上使用视图绑定
How to use View Binding on custom views
视图绑定已作为 Android Jetpack
的一部分发布
文档:https://developer.android.com/topic/libraries/view-binding
我的问题是,如何将视图绑定与自定义视图结合使用。 Google 文档只有展示 Activity 和片段。
我试过了,但是没有显示。
LayoutInflater inflater = LayoutInflater.from(getContext());
然后,我用了这个,但还是不行。
LayoutInflater inflater = (LayoutInflater)
getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
我想我可能没有针对我的视图定位正确的布局 inflater 但不确定。
要使用视图绑定,您需要使用生成的绑定 class 而不是 LayoutInflater
,例如,如果布局名称是 result_profile.xml
那么您需要使用 ResultProfileBinding
为:
class CustomView @kotlin.jvm.JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private lateinit var binding: ResultProfileBinding
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context))
addView(binding.root)
}
}
- 自动生成 class :
result_profile.xml
-> ResultProfileBinding
(布局名称,附加 Binding
)
膨胀绑定
ResultProfileBinding.inflate(LayoutInflater.from(context))
使用 addView
将视图添加到层次结构中:
addView(binding.root)
注意:如果您从 ConstraintLayout
(是父 class)扩展,则使用
如果您尝试将视图绑定与根视图一起使用,这对我有用:
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)
}
}
只需通知根,是否要附加到它
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context), this)
}
或
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context), this, true)
}
使用哪种 inflate 方法将取决于 xml 中的根布局类型。
这是我能想到的最简单的 kotlin 答案。它是一个自定义视图,仅包装了一个 TextView 并提供了一个 update(s:String)
函数来更新文本。
<!-- 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
}
}
我喜欢这个答案的两点是:
binding
是 val
而不是 var
。我尽量限制 var
的数量。
-
addView
与 val binding
密切相关,使用 also {}
范围函数而不是 init {}
子句,使 View
实例化感觉更加明确。
有人可能会争辩说 addView()
确实是一种副作用,应该在 init {}
部分中,以便它与 binding
val 的声明分开。我会反驳 - 声明一个 val
然后将它提供给需要它的一段代码,这对我来说并不是副作用。
您可以立即初始化视图绑定属性
private val binding = CustomViewBinding.inflate(LayoutInflater.from(context), this)
视图绑定已作为 Android Jetpack
的一部分发布文档:https://developer.android.com/topic/libraries/view-binding
我的问题是,如何将视图绑定与自定义视图结合使用。 Google 文档只有展示 Activity 和片段。
我试过了,但是没有显示。
LayoutInflater inflater = LayoutInflater.from(getContext());
然后,我用了这个,但还是不行。
LayoutInflater inflater = (LayoutInflater)
getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
我想我可能没有针对我的视图定位正确的布局 inflater 但不确定。
要使用视图绑定,您需要使用生成的绑定 class 而不是 LayoutInflater
,例如,如果布局名称是 result_profile.xml
那么您需要使用 ResultProfileBinding
为:
class CustomView @kotlin.jvm.JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private lateinit var binding: ResultProfileBinding
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context))
addView(binding.root)
}
}
- 自动生成 class :
result_profile.xml
->ResultProfileBinding
(布局名称,附加Binding
) 膨胀绑定
ResultProfileBinding.inflate(LayoutInflater.from(context))
使用
addView
将视图添加到层次结构中:addView(binding.root)
注意:如果您从 ConstraintLayout
(是父 class)扩展,则使用
如果您尝试将视图绑定与根视图一起使用,这对我有用:
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)
}
}
只需通知根,是否要附加到它
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context), this)
}
或
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context), this, true)
}
使用哪种 inflate 方法将取决于 xml 中的根布局类型。
这是我能想到的最简单的 kotlin 答案。它是一个自定义视图,仅包装了一个 TextView 并提供了一个 update(s:String)
函数来更新文本。
<!-- 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
}
}
我喜欢这个答案的两点是:
binding
是val
而不是var
。我尽量限制var
的数量。-
addView
与val binding
密切相关,使用also {}
范围函数而不是init {}
子句,使View
实例化感觉更加明确。
有人可能会争辩说 addView()
确实是一种副作用,应该在 init {}
部分中,以便它与 binding
val 的声明分开。我会反驳 - 声明一个 val
然后将它提供给需要它的一段代码,这对我来说并不是副作用。
您可以立即初始化视图绑定属性
private val binding = CustomViewBinding.inflate(LayoutInflater.from(context), this)