使用数据绑定设置视图可见性

142

尝试使用自定义变量设置View的可见性,但出现错误:标识符必须从XML文件具有用户定义的类型。visible 缺失了它。是否可能使用数据绑定设置视图可见性?谢谢。

<data>
    <variable
        name="sale"
        type="java.lang.Boolean"/>
</data>

<FrameLayout android:visibility="@{sale ? visible : gone}"/>

4个回答

342

正如在Android开发者指南中所述,您需要这样做:

<data>
    <import type="android.view.View"/>
    <variable
        name="sale"
        type="java.lang.Boolean"/>
</data>

<FrameLayout android:visibility="@{sale ? View.GONE : View.VISIBLE}"/>

7
如何将“sale”设置为特定的值? - RobinHood
那么你的意思是如何将值“sale”分配给一个字符串变量? - David Artmann
没错!我遇到了一个问题。请分享,我会进行比较然后告诉你。 - RobinHood
58
该死!我错过了这个愚蠢的import。好了,谢谢。 - RobinHood
我没有看到代码有任何问题,但我怀疑这并不足以分析您的问题。也许您可以提供一个完全运行的示例,让我可以测试一下(例如一个样本 GitHub 存储库)? - David Artmann
显示剩余3条评论

69

在您的布局中:

<data>
    <variable
        name="viewModel"
        type="...."/>
</data>


<View
 android:layout_width="10dp"
 android:layout_height="10dp"
 android:visibility="@{viewModel.saleVisibility, default=gone}"/>

在你的ViewModel Java代码中:

@Bindable
public int getSaleVisibility(){
 return mSaleIndecator ? VISIBLE : GONE;
}

4
你救了我一个小头疼。 - vanlooverenkoen
2
你的数据模型必须是可观察的才能使其工作。 - yshahak
这对我起作用,而且没有包括@Bindable。当我包括它时,我得到了不同的绑定错误,包括建议扩展BaseObservable。这里有一个好的指针。 - Gene Bo
2
必须是被接受的答案!它对我完美地起作用了! - Crisic
1
LiveData<Boolean> 有什么建议吗? - Sourav Bagchi

50
问题在于View类上的visibility是一个整数类型,这意味着您有两种方法可以使其工作:
  1. 使用View.VISIBLEView.GONE常量。https://developer.android.com/topic/libraries/data-binding/index.html#imports
  2. visibility定义一个自定义setter,该setter接受一个Boolean参数。https://developer.android.com/topic/libraries/data-binding/index.html#custom_setters
可能的实现方式:
@BindingAdapter("android:visibility")
public static void setVisibility(View view, Boolean value) {
    view.setVisibility(value ? View.VISIBLE : View.GONE);
}

这将使得<FrameLayout android:visibility="@{sale}"/>正常工作。


4
在方便的情况下,注解处理器会在编译期间自动检测它们。 - Kiskae
谢谢,我已经把它放在我的BindingUtils.java文件中了。 - nhoxbypass
但是如何设置销售价呢? - EslamWael74
1
我如何将相同的方法应用于<include>标签? - Zafer Celaloglu
1
@EslamWael74 你可以通过 Java/Kotlin 代码中的绑定设置 sale 的值。类似于 val binding = MyClassBinding.inflate(...),然后你只需要调用 binding.sale = true 即可。 - Matt Robertson

5

类似于Kiskae的解决方案。将此方法放入一个单独的文件中,例如Bindings.kt:

@BindingAdapter("android:visibility")
fun View.bindVisibility(visible: Boolean?) {
    isVisible = visible == true
    // visibility = if (visible == true) View.VISIBLE else View.GONE
}

然后在布局XML中:

<data>

    <variable
        name="viewModel"
        type="SomeViewModel" />
</data>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="@{viewModel.number == 1}" />

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