如何通过 DataBinding 设置 ConstraintLayout 组的可见性?
How can I set a ConstraintLayout Group's visibility via DataBinding?
我的布局中有 2 个 Group
用于控制视图的可见性。
但是,我无法通过 DataBinding 设置它们的可见性:
<layout>
<data>
<import type="android.view.View"/>
<variable
name="viewModel"
type="co.aresid.book13.fragments.trackinglist.TrackingListViewModel"
/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout>
...
<androidx.constraintlayout.widget.Group
android:id="@+id/content_group"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="@{viewModel.hideLoadingAndShowContent ? View.VISIBLE : View.GONE, default=gone}"
app:constraint_referenced_ids="tracking_list_recycler_view"
/>
<androidx.constraintlayout.widget.Group
android:id="@+id/loading_group"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="@{viewModel.hideLoadingAndShowContent ? View.GONE : View.VISIBLE, default=visible}"
app:constraint_referenced_ids="progress_circular"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
hideLoadingAndShowContent
变量是一个 LiveData
,它从我的 ViewModel
:
中相应的 MutableLiveData
获取值
private val _hideLoadingAndShowContent = MutableLiveData<Boolean>()
val hideLoadingAndShowContent: LiveData<Boolean>
get() = _hideLoadingAndShowContent
这个LiveData
只在ViewModel
中设置,不会出现在Fragment
中 class.
在 Fragment
class 中,我还设置了 binding.lifecycleOwner
:
binding.lifecycleOwner = viewLifecycleOwner
我错过了什么细节?
因为android:visibility
不支持绑定变量观察,
您可以通过这种方式创建 BindingAdapter
@BindingAdapter("mutableVisibility")
fun setMutableVisibility(view: View, visibility: MutableLiveData<Boolean>) {
val owner = (view.getParentActivity() ?: view.context) as LifecycleOwner
if (owner != null) {
visibility.observe(
owner,
Observer { value ->
view.visibility = if(value) View.VISIBLE else View.GONE
})
}
}
从视图中获取 activity 的实用函数。
fun View.getParentActivity(): AppCompatActivity?{
var context = this.context
while (context is ContextWrapper) {
if (context is AppCompatActivity) {
return context
}
context = context.baseContext
}
return null
}
然后在你的XML中你可以这样做
<androidx.constraintlayout.widget.Group
android:id="@+id/content_group"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="@{viewModel.hideLoadingAndShowContent}"
app:constraint_referenced_ids="tracking_list_recycler_view"
/>
我忘记将 ViewModel
传递给 Fragment
中的布局绑定 class:
binding.viewModel = viewModel
我的布局中有 2 个 Group
用于控制视图的可见性。
但是,我无法通过 DataBinding 设置它们的可见性:
<layout>
<data>
<import type="android.view.View"/>
<variable
name="viewModel"
type="co.aresid.book13.fragments.trackinglist.TrackingListViewModel"
/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout>
...
<androidx.constraintlayout.widget.Group
android:id="@+id/content_group"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="@{viewModel.hideLoadingAndShowContent ? View.VISIBLE : View.GONE, default=gone}"
app:constraint_referenced_ids="tracking_list_recycler_view"
/>
<androidx.constraintlayout.widget.Group
android:id="@+id/loading_group"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="@{viewModel.hideLoadingAndShowContent ? View.GONE : View.VISIBLE, default=visible}"
app:constraint_referenced_ids="progress_circular"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
hideLoadingAndShowContent
变量是一个 LiveData
,它从我的 ViewModel
:
MutableLiveData
获取值
private val _hideLoadingAndShowContent = MutableLiveData<Boolean>()
val hideLoadingAndShowContent: LiveData<Boolean>
get() = _hideLoadingAndShowContent
这个LiveData
只在ViewModel
中设置,不会出现在Fragment
中 class.
在 Fragment
class 中,我还设置了 binding.lifecycleOwner
:
binding.lifecycleOwner = viewLifecycleOwner
我错过了什么细节?
因为android:visibility
不支持绑定变量观察,
您可以通过这种方式创建 BindingAdapter
@BindingAdapter("mutableVisibility")
fun setMutableVisibility(view: View, visibility: MutableLiveData<Boolean>) {
val owner = (view.getParentActivity() ?: view.context) as LifecycleOwner
if (owner != null) {
visibility.observe(
owner,
Observer { value ->
view.visibility = if(value) View.VISIBLE else View.GONE
})
}
}
从视图中获取 activity 的实用函数。
fun View.getParentActivity(): AppCompatActivity?{
var context = this.context
while (context is ContextWrapper) {
if (context is AppCompatActivity) {
return context
}
context = context.baseContext
}
return null
}
然后在你的XML中你可以这样做
<androidx.constraintlayout.widget.Group
android:id="@+id/content_group"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="@{viewModel.hideLoadingAndShowContent}"
app:constraint_referenced_ids="tracking_list_recycler_view"
/>
我忘记将 ViewModel
传递给 Fragment
中的布局绑定 class:
binding.viewModel = viewModel