【问题标题】:Two-way data binding for android:enabled attributeandroid:enabled 属性的双向数据绑定
【发布时间】:2017-03-18 18:28:24
【问题描述】:

我正在尝试找出 Android 中的双向数据绑定库。我想通过更改 xml 中的 android:enabled 属性来启用/禁用 LinearLayout(以及内部的 RelativeLayout)。

XML 部分如下所示:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center_vertical"
    android:layout_margin="5dp"
    android:gravity="center"
    android:enabled="@={viewModel.asd}"
    ndroid:onClick="@{()-> viewModel.doSomething()}"
    android:background="@drawable/shortcut_button_label_selector"
    android:orientation="horizontal">

    <RelativeLayout
        android:layout_width="40dp"
        android:layout_height="match_parent"
        android:enabled="@={viewModel.asd}"
        android:background="@drawable/shortcut_button_icon_selector">

现在,我之所以要这样做是因为这两个选择器(shortcut_button_label_selector 和shortcut_button_icon_selector),它们看起来像这样:

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

    <item
        android:state_enabled="false"
        android:drawable="@color/grey_300"></item>
    <item
        android:state_enabled="true"
        android:drawable="@color/menubar_background"></item>

</selector>

我希望能够根据视图上的启用属性动态更改背景。我选择启用属性的原因是我在 LinearLayout 上获得了 onClick 事件,我需要禁用它(使其不可点击);我对 android:clickable 属性有同样的问题。

问题是当我尝试编译它时出现错误

java.lang.RuntimeException:发现数据绑定错误。 ****/ 数据绑定错误 ****msg:在 android.widget.LinearLayout 上找不到属性“android:enabled”的 getter,其值类型为布尔值。

viewModel.asd 只是一个公共布尔值/ ObservableBoolean,我都试过了。

谁能解释发生了什么以及为什么我会收到错误消息?我可以在 View 类(布局扩展)中看到 isEnabled / setEnabled 方法。

我有什么办法可以继续我的方法,还是我必须完全改变它?

//编辑:我可能不需要双向绑定..我不知道了 // 继续编辑:它可能与我的 ViewModel 继承有关:

布局文件有一个 a.b.MainViewModel 类型的 viewModel,但字段 asd 位于 a.b.BaseViewModel 中(MainViewModel 扩展了 BaseViewModel)。现在我想要的是,如果我从扩展 BaseViewModel 的任何其他视图更新 asd 字段,它将自动更新启用的属性..

它也不适用于字符串。我猜这是继承的事情

亲切的问候, 马辛

【问题讨论】:

  • asd 是静态字段吗?

标签: android android-databinding 2-way-object-databinding


【解决方案1】:

您的错误可能有多种原因。首先是 2-way 数据绑定不适用于 android:enabled 属性。这是因为没有回调告诉数据绑定属性已更改。

2-way 数据绑定适用于用户输入数据的大多数属性,因此最容易将其视为将数据从用户获取到模型。

您可能会收到类似错误的另一个原因是模型可能没有可绑定属性。您应该使用 Observable:

public class ViewModel extends BaseObservable {
    private boolean asd = true;

    @Bindable
    public boolean getAsd() { return asd; }

    public void setAsd(boolean asd) {
        this.asd = asd;
        notifyPropertyChanged(this, BR.asd);
    }
}

或使用 ObservableFields:

public class ViewModel {
    public final ObservableBoolean asd = new ObservableField(true);
}

没有这个,一种数据绑定方式只能在第一次工作——如果您更改 ViewModel,UI 将不会更新。

您似乎不需要android:enabled 属性的双向数据绑定。一种数据应该可以正常工作以更改选择器的状态。

【讨论】:

  • 难道不能劫持drawable状态来获取2路绑定的启用状态变化信息吗?
  • 这不是获取启用状态的问题,而是在启用状态发生变化时能够得到通知的问题。启用更改时没有外部通知,因此默认情况下 2-way 数据绑定不起作用。如果您添加自己的(创建一个侦听器并覆盖允许更改的内容),那么您可以为侦听器创建一个带有附加 BindingAdapter 的 2-way 表达式。见medium.com/google-developers/…
【解决方案2】:

所以,我试图缩小问题的原因,只有在我将编辑添加到我以前的帖子之后,我才意识到继承可能确实有问题。

基本上,我所拥有的是主 Activity(称为 MainActivity)的绑定以及在该 Activity 内被替换的片段的单独绑定。两个绑定的视图模型都扩展了保存该布尔值的 BaseViewModel。主要活动绑定必须在每个片段更新时更新(比如我必须根据我实际所在的片段隐藏/显示某些内容)。

现在,我期望发生的是,如果我在 MainActivityViewModel 中设置布尔值(实际上会在基类中设置值 AND 替换扩展基类的另一个 ViewModel 中的“that”字段前者会更新...傻我,我意识到我必须直接更新 MainViewModel 中的布尔值。这是基本的 Java 概念,与 Android 无关..

不过,我不知道如何解释的一件事是,这个布尔值是从 java.util.Set#contains 方法返回的。我有一个 ObservableField observableSet(现在在 MainViewModel 中)和方法 isInTheSet(Object) 返回 set.contains(Object)

当我在 xml 文件 (viewModel.isInTheSet(Object)) 中执行该方法时,当我更改 ObservableField 值时它没有更新视图。但是,当我将 xml 更改为使用 viewModel.observableSet.contains(Object) 时,它起作用了。谁能解释一下?

很抱歉在这里造成了混乱,我昨天工作了很长时间。

//编辑:是的,我不需要双向绑定..

马辛

【讨论】:

    猜你喜欢
    • 2014-02-21
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 2012-06-20
    • 2012-12-17
    • 1970-01-01
    • 2020-04-13
    相关资源
    最近更新 更多