使用 Observable 布尔值设置 android 视图的可见性

Using Observable Boolean to set visibility of an android view

这是关于我在代码审查中一直争论不休的一些非常微不足道的事情。情景是这样的。有一个数据绑定布局:some_layout.xml,由 ViewModel.

支持

[some_layout.xml 的内容]

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="android.view.View"/>
        <variable name="viewModel" type="some.long.package.name.SomeViewModel"/>
    </data>

    <!-- Other stuffs -->

    <TextView
        <!-- Other parameters-->>
        android:visibility="@{viewModel.someObservableBool?View.VISIBLE : View.GONE}"
    />
</layout>

要求,当布尔值是 false 时,我希望 TextViewView.GONE(而不是 View.INVISIBLE)。我的代码的审阅者坚持这个事实,我应该直接使用布尔值而不是三元运算符 android:visibility[android:visibility="@{viewModel.someObservableBool}"]

现在我的理解是因为真值隐式转换为int会导致视图是Visible/Invisible而不是Gone。正如 attrs.xml 定义所述,

<!-- Controls the initial visibility of the view.  -->
<attr name="visibility">
    <!-- Visible on screen; the default value. -->
    <enum name="visible" value="0" />
    <!-- Not displayed, but taken into account during layout (space is left for it). -->
    <enum name="invisible" value="1" />
    <!-- Completely hidden, as if the view had not been added. -->
    <enum name="gone" value="2" />
</attr>

我的理解有误吗?

java 中没有隐式类型转换,整数值不会被解释为布尔值 - 这意味着如果你写

 <TextView
        <!-- Other parameters-->>
        android:visibility="@{viewModel.someObservableBool}"
    />

它只是不会编译。

但是如果你加上

@BindingConversion
fun booleanToVisibility(value: Boolean?) = if (value == true)View.VISIBLE else View.GONE

应该可以。您可以查看相关文档here

我正在以这种方式使用它进行电子邮件验证,ObservableBoolean:

XML:

<data>

    <import type="android.view.View" />

    <variable
        name="isProperEmail"
        type="androidx.databinding.ObservableBoolean" />
</data>

<!--    your other code here-->

    <androidx.appcompat.widget.AppCompatImageView
            ---------
            ---------
            android:visibility="@{isProperEmail ?View.VISIBLE : View.GONE}" />

并在 class 中使用它:

private val isProperEmail = ObservableBoolean(false)

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    -------------

    binding.isProperEmail = isProperEmail
}

现在,每当您更改此 class' isProperEmail 变量的值时,它都会更改并影响到 XML/Layout.

如果在 XML

中导入 viewModelView 实例,我会采用以下方法
<TextView
    android:visibility="@{(viewModel.someObservableBool())? View.VISIBLE : View.GONE}" />

无需导入 Observable 变量,因为 viewModel 在此上下文中已经可用。