如何在内部控件中传递ObservableField

时间:2016-08-10 14:38:46

标签: java android data-binding android-databinding

主视图模型如下所示:

class MainVM{
    public ObservableField<String> title;
    public ObservableField<Boolean> isFlexible;
}

主要布局如下:

<layout>
  <date><variable name="item" type="MainVM"></data>
  <LinearLayout>
     <TextView text="@{item.title}"/>
     <CustomCtrl1 vm="@{item.isFlexible}">
  </LinearLayout>
</layout>

CustomCtrl的布局看起来有点像

   <layout>
      <date><variable name="item" type="boolean"></data>
      <LinearLayout>
          ...
         <Switch checked="@{item}"/>
          ...
      </LinearLayout>
    </layout>

问题是ObservableField MainVM转换为布尔值时传递给CustomCtrl,然后更改CustomCtrl内的布尔值。影响MainVM&#39; s。第一个想法是将CustomCtrl's视图模型从Boolean更改为ObservableField<Boolean>但由于某种原因不允许这样做。

所以问题是 - 在内部控制中传递ObservableField的正确方法是什么。

1 个答案:

答案 0 :(得分:1)

执行此操作的最佳方法是直接使用双向绑定。这需要Android Studio 2.1及更高版本。 Android Studio 2.2修复了使用自定义控件可能遇到的通胀错误。如果你使用了include而不是自定义控件,那将是相当简单的:

<layout>
  <date><variable name="item" type="MainVM"></data>
  <LinearLayout>
     <TextView android:text="@{item.title}"/>
     <include layout="@layout/other" app:vm="@={item.isFlexible}">
  </LinearLayout>
</layout>

和其他人的布局:

<layout>
  <date><variable name="item" type="boolean"></data>
  <LinearLayout>
      ...
     <switch android:checked="@={item}"/>
      ...
  </LinearLayout>
</layout>

使用自定义控件,您必须自己实现侦听器。这意味着您必须拥有该属性的侦听器。我认为这应该有用(我现在在平板电脑上,所以我无法验证):

@InverseBindingMethods({
     InverseBindingMethod(type = CustomControl.class, attribute="vm")})
public class CustomCtrl extends View {
    private CustomCtrlBinding binding;
    private InverseBindingAdapter listener;

    public CustomCtrl(...) {
        binding = ...
        binding.addOnPropertyChangedCallback(new OnPropertyChangedCallback() {
            @Overriide
            public void OnPropertyChanged(Observable sender, int propertyId) {
                if (listener != null) {
                    listener.onChange();
                }
            }
        });
    }

    @Bindable
    public boolean getVm() { return binding.getItem(); }

    public void setVm(boolean vm) {
        binding.setItem(vm);
    }

    @BindingAdapter("vmAttrChanged")
    public static void setListener(CustomCtrl view,
            InverseBindingListener listener) {
        view.listener = listener;
    }
}

然后你有双向绑定:

<layout>
  <date><variable name="item" type="MainVM"></data>
  <LinearLayout>
     <TextView android:text="@{item.title}"/>
     <CustomCtrl app:vm="@={item.isFlexible}">
  </LinearLayout>
</layout>

自定义控件布局:

<layout>
  <date><variable name="item" type="boolean"></data>
  <LinearLayout>
      ...
     <switch android:checked="@={item}"/>
      ...
  </LinearLayout>
</layout>

我通常会编写一个自定义控件,该控件具有自己的属性侦听器,但InverseBindingListener可以处理。