android:enabled属性的双向数据绑定

时间:2017-03-18 18:28:25

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

我正试图找出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>

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

当我尝试编译它时,我收到了错误

  

java.lang.RuntimeException:发现数据绑定错误。   **** /数据绑定错误****消息:在android.widget.LinearLayout上找不到值类型为boolean的属性'android:enabled'的getter。

viewModel.asd 只是一个公共boolean / ObservableBoolean,我已经尝试了两种方法。

任何人都可以解释发生了什么,为什么我会收到错误?我可以在View类中看到 isEnabled / setEnabled 方法(Layouts扩展)。

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

//编辑:我可能不需要双向绑定..我不知道了 //编辑继续:它可能需要对我的ViewModel继承做一些事情:

布局文件的viewModel类型为a.b.MainViewModel,但字段asd是a.b.BaseViewModel(MainViewModel扩展BaseViewModel)。现在我想要的是如果我从扩展BaseViewModel的任何其他视图更新asd字段,它会自动更新enabled属性..

它也不适用于Strings ..我猜这是继承的事情

亲切的问候, 马尔钦

2 个答案:

答案 0 :(得分:2)

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

双向数据绑定适用于用户输入数据的大多数属性,因此最简单的方法是将数据视为从用户获取数据到模型。

您可能收到类似错误的另一个原因是该模型可能没有可绑定属性。您应该使用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属性的双向数据绑定。一种方法数据应该可以正常工作来改变选择器的状态。

答案 1 :(得分:0)

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

基本上,我所拥有的是主Activity的绑定(称为MainActivity)以及在该活动内被替换的片段的单独绑定。两个绑定的视图模型都在扩展保存该布尔值的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)时,它工作了..任何人都可以解释一下吗?

很抱歉在这里造成大规模混乱,我昨天上班很长一段时间。

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

的Marcin