我想创建一个“ inflateWhen” BindingAdapter并将其附加到一个viewtub中,以便在布尔值为true时使其膨胀。但是,BindingAdapter一直试图在viewstub的根视图上进行操作,从而导致其无法编译。有什么方法可以作为绑定适配器来执行此操作,而不必在活动中以编程方式执行此操作吗?
这是我到目前为止的内容:
@BindingAdapter("inflateWhen")
fun inflateWhen(viewstub: ViewStub, inflate: Boolean) {
if (inflate) {
viewstub.inflate()
} else {
viewstub.visibility = View.GONE
}
}
这就是我所拥有的,但是当连接到像这样的viewstub时
<ViewStub
android:id="@+id/activity_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:inflateWhen="@{viewmodel.userid != 0}" />
它无法编译。错误是:
ActivityMyAccountSectionedBindingImpl.java:1087: error: cannot find symbol
if (this.pageFooter.isInflated()) this.pageFooter.getBinding().setVariable(BR.inflateWhen, viewmodelRatingInt0);
看起来它正在尝试将绑定应用于膨胀视图,但这不是我想要的。
答案 0 :(得分:1)
2020年10月10日更新:
我已经在Medium上写了一篇文章,其中提供了一个示例,该示例演示如何使用ViewStub和DataBinding根据屏幕状态动态切换布局:
https://medium.com/@mxdiland/viewstub-databinding-handle-screen-states-easily-2f1c01098b87
旧的可接受答案:
我还面临为@BindingAdapter
编写ViewStub
的问题,以使用数据绑定而不是直接引用ViewStub
并调用inflate()
一路走来,我做了一些调查,研究了以下内容:
ViewStub
必须具有android:id
属性,以避免类似 java.lang.IllegalStateException:target.id不能为null的构建错误; ViewStub
编写任何绑定适配器都不会被数据绑定使用的原因@BindingAdapter
却很棘手,它起作用:androidx.databinding.adapters.ViewStubBindingAdapter
并允许通过XML属性ViewStub.OnInflateListener
设置android:onInflate
ViewStubBindingAdapter
的第一个参数是ViewStubProxy
而不是View
或ViewStub
!; androidx.databinding.adapters.ViewStubBindingAdapter
并实现一些所需的逻辑。因为此适配器是使用数据绑定与ViewStub
进行交互的唯一选择,所以我决定覆盖该适配器,而不将其用于其预期目的
这个想法是提供特定的ViewStub.OnInflateListener
,它将是侦听器本身,同时也表示应该调用ViewStub.inflate()
:
class ViewStubInflationProvoker(
listener: ViewStub.OnInflateListener = ViewStub.OnInflateListener { _, _ -> }
) : ViewStub.OnInflateListener by listener {
companion object {
@JvmStatic
fun provideIf(clause: Boolean): ViewStubInflationProvoker? {
return if (clause) {
ViewStubInflationProvoker()
} else {
null
}
}
}
}
以及覆盖绑定适配器:
@BindingAdapter("android:onInflate")
fun setOnInflateListener(
viewStubProxy: ViewStubProxy,
listener: ViewStub.OnInflateListener?
) {
viewStubProxy.setOnInflateListener(listener)
if (viewStubProxy.isInflated) {
viewStubProxy.root.visibility = View.GONE.takeIf { listener == null } ?: View.VISIBLE
return
}
if (listener is ViewStubInflationProvoker) {
viewStubProxy.viewStub?.inflate()
}
}
和XML部分
...
<ViewStub
android:id="@+id/no_data_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/no_data"
android:onInflate="@{ViewStubInflationProvoker.provideIf(viewModel.state == State.Empty.INSTANCE)}"
app:viewModel="@{viewModel.noDataViewModel}"
/>
...
因此,现在仅当状态为State.Empty
且数据绑定会将 viewModel 变量设置为膨胀的@layout/no_data
布局时,才会发生通货膨胀。
不是很优雅,但是可行的解决方案。