Android 如何在自定义视图上使用视图绑定

Android 如何在自定义视图上使用视图绑定,android,android-custom-view,android-viewbinding,Android,Android Custom View,Android Viewbinding,视图绑定作为Android Jetpack的一部分发布 文件: 我的问题是,如何对自定义视图使用视图绑定。谷歌文档只显示了案例活动和片段 我试过了,但什么也没显示出来 LayoutInflater inflater = LayoutInflater.from(getContext()); 然后,我用了这个,但同样,没有运气 LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(C

视图绑定作为Android Jetpack的一部分发布

文件:

我的问题是,如何对自定义视图使用视图绑定。谷歌文档只显示了案例活动和片段

我试过了,但什么也没显示出来

LayoutInflater inflater = LayoutInflater.from(getContext());
然后,我用了这个,但同样,没有运气

LayoutInflater inflater = (LayoutInflater)
            getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

我想可能我的视图没有针对正确的布局充气器,但不确定。

要使用视图绑定,需要使用生成的绑定类,而不是
LayoutInflater
,例如,如果布局名称是
result\u 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)
    }

}

  • 自动生成的类:
    result\u profile.xml
    ->
    ResultProfileBinding
    (布局名称,附加有
    绑定
  • 给装订线充气

    ResultProfileBinding.inflate(LayoutInflater.from(context))
    
  • 使用
    addView
    在层次结构中添加视图,如下所示:

    addView(binding.root)
    

  • 注意:如果您是从
    ConstraintLayout
    (父类)扩展,那么请使用如果您试图使用根视图的视图绑定,这对我很有用:

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

    这是我能想到的最简单的科特林答案。它是一个自定义视图,只包装一个文本视图,并提供一个
    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
        }
    }
    
    
    //StubView.kt
    类StubView@JVM重载构造函数(
    上下文:上下文,
    属性集?=null,
    defStyleAttr:Int=0
    ):FrameLayout(上下文、属性、defStyleAttr){
    val binding=ViewStubBinding.inflate(context.getSystemService(context.LAYOUT\u INFLATER\u SERVICE)作为LayoutInflater)
    .allow{addView(it.root)}
    趣味更新(updateText:String){
    binding.myTextView.text=updatedText
    }
    }
    
    我喜欢这个答案的两个方面是:

  • binding
    val
    而不是
    var
    。我尽量限制
    var
    s的数量
  • addView
    val绑定
    密切相关,它使用
    还{}
    作用域函数而不是
    init{}
    子句,使得
    视图的实例化更具声明性

  • 有人可能会说,
    addView()
    实际上是一个副作用,应该在
    init{}
    节,使其与
    绑定的声明分开。我的观点正好相反——声明
    val
    然后将其提供给需要它的代码节,对我来说不会产生副作用。

    您可以立即初始化视图绑定属性

    private val binding = CustomViewBinding.inflate(LayoutInflater.from(context), this)
    


    请参阅绑定适配器:@ruthwikwarier您能详细说明一下吗?因为我问的是关于视图绑定而不是数据绑定。有一个类似的问题,答案是正确的:@ruthwikwarier很抱歉不同意,但问题是关于视图绑定而不是数据绑定,因为youThanks提供了链接。您的回答在某些方面可能会有所帮助,但我需要一种使用视图绑定的方法来扩展根视图,而不是将视图添加到根视图中。@EmiRaz如果您的自定义视图已创建(java/kotlin)然后在XML布局中添加自定义视图,然后可以从
    绑定
    对象作为
    绑定直接访问自定义视图。自定义视图
    ,或者如果您想按听起来的方式使用视图绑定(
    如何将视图绑定与自定义视图
    ),请按照答案进行操作。仅供参考:
    inflater
    用于使用xml布局对新视图进行充气。如果在init块中对视图本身进行充气(正如@EmiRaz所要求的),则最终将进入无限循环,充气将再次调用init块。他在问如何在
    CustomView
    @Downvoter中使用
    CustomViewBinding
    :我可以知道downvote的原因吗?我已经清楚地添加了关于如何使用带有视图绑定的自定义视图的详细信息,并在中的OP中添加了缺少的详细信息comments@JasonToms为什么它会创建一个循环,你测试过吗?由于我们将在自定义视图中使用生成的布局绑定类,恐怕您还有其他情况,因为它无法按照您建议的方式工作,并且与NPE一起崩溃,因为此自定义视图布局中没有为ID生成任何内容。这会泄漏内存吗?在片段中,在
    onDestory
    中取消引用绑定很重要,从现有布局资源中展开视图怎么样?像
    init{inflate(context,R.layout.my_view,this)}
    ResultProfileBinding
    正在引用布局资源。在您的情况下,它将是
    MyViewBinding.inflate(..)
    。我是否应该将
    binding
    变量设置为
    null
    的某个位置,类似于如何设置?我们是否需要将引用设置为null的某个位置?附加的绑定参数是这里比较棘手的部分,尤其是
    这个
    。为什么不简单地
    attachToParent=true
    打开
    inflate()
    ?应该是同等的。