如何在Android中使用ViewBinding展开ViewStub

11

由于 Kotlin Synthetics 已被弃用,我们正在迁移到 ViewBinding。

我尝试了很多搜索和阅读关于 ViewStub、ViewBinding 的文档,并实现了 ViewBinding 用于 Fragments Activities、include、merge 标签,但我找不到任何使用 ViewBinding 来充气 ViewStub 的方法。

 <ViewStub
            android:id="@+id/viewStubLayout"
            tools:layout="@layout/view_demo_layout" />

请忽略此处的宽度和高度属性,它们仅作为样式添加,并已从此段代码中删除。
请问您能否分享如何使用ViewBinding动态地将另一个XML布局填充到此视图中?
即使在ViewStub.java文件中,类级别的注释也指出:
“执行布局资源的膨胀的首选方法如下:
ViewStub stub = findViewById(R.id.stub);
View inflated = stub.inflate();

这是否意味着我必须继续使用R.layout.xxx_xx来填充viewstub? 我不能使用该特定xml文件的绑定对象来填充吗?

通货膨胀就像只有 stub.inflate() 这样。如果你想要绑定对象,那么可以通过 DataBindingUtil.bind(inflated) 来获取它。 - ADM
@ADM 问题是在这一行中,是否可以使用生成的绑定类ViewDemoLayoutBinding,而不是在此处使用R.layout.stub:ViewStub stub = findViewById(R.id.view_demo_layout)? - Karan Sharma
另外,DataBindingUtil是什么?我没有使用DataBinding,而是使用ViewBinding。 - Karan Sharma
你可以在绑定类上调用 ViewDemoLayoutBinding.bind(),而不是使用 DataBindingUtil,这两者是相同的。 - ADM
3个回答

12

我曾经写过一篇文章介绍了在Beta版中的ViewBinding。除了ViewStub之外,我涵盖了每种情况。 ViewStub的情况与我链接文章中的<Include>情况非常相似。您需要做的就是调用您添加ViewStub的根视图上的bind()函数。请记得在setOnInflateListener中调用bind()

class MainFragment : Fragment() {
private var binding: FragmentMainBinding by autoCleared()
private var stubBinding: StubBinding by autoCleared()

  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
      binding = FragmentMainBinding.inflate(inflater, container, false)
      binding.stub.setOnInflateListener { _, inflateId -> stubBinding = StubBinding.bind(inflateId) }
      return binding.root
  }

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
      super.onViewCreated(view, savedInstanceState)
      binding.stub.inflate()
      stubBinding.tvTestMe.text = "Hurray"
   }
}

1
“by autoCleared” 这个词从哪里来的? - Andrew
@Andrew 你可以在谷歌的GitHub浏览器示例中找到它。 - Somesh Kumar
谢谢您的回答。问题:在ViewStub中双向数据绑定怎么实现?普通的"@={text}"无法使用。 - Andrew
1
@Andrew 我不使用数据绑定,所以我无法回答。抱歉! - Somesh Kumar
难道 stub 的原因不是为了能够动态地切换布局吗?例如,如果您想根据一个类型变量来决定要将哪个布局填充到 stub 中,那么上述方法会将您限制在 stubBinding 变量的类型必须与我填充的布局相匹配,是吗?是否有一种方法可以不直接依赖于包含的布局(假设两个可能的布局中的 ID 相同),并且能够通过支持两个布局的 stubBinding 变量访问包含的布局? - undefined

4

@Somesh 的回答中有一个小错误需要更正。

传递给 StubBinding 的膨胀视图是错误的。实际上,我们应该传递从 onInflate 监听器接收到的视图。

class MainFragment : Fragment() {
private var binding: FragmentMainBinding by autoCleared()
private var stubBinding: StubBinding by autoCleared()

  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
      binding = FragmentMainBinding.inflate(inflater, container, false)
      binding.stub.setOnInflateListener { _, inflated -> stubBinding = StubBinding.bind(inflated) }
      return binding.root
  }

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
      super.onViewCreated(view, savedInstanceState)
      binding.stub.inflate()
      stubBinding.tvTestMe.text = "Hurray"
   }
}

原始答案已被编辑以修复此问题。 - Vince

0

这可以通过两行简单的代码完成

binding.viewStub.layoutResource = R.layout.layoutId
binding.viewStub.inflate()

1
这个答案缺少一行重要的代码:存根的绑定。stubBinding = StubBinding.bind(inflated),其中inflated是从第2行返回的视图。 - wize

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接