[Android] DataBinding自定义View双向绑定

问题描述

包含EditText的自定义View需要实现双向绑定,即在用户输入时,对应的Observable变量能够实时获取最新值。

实现方案

适用BindingAdapter实现EditText文本的set方法。在赋值前需要判断是否与原值相等,如果相等则不重新set,因为set方法会触发下面的get方法,若不判断是否相等会引起死循环。

@BindingAdapter("value")
public static void setValue(CustomLayout customLayout, String value) {
        if (customLayout != null) {
            String edTextString = customLayout.etContent.getText() == null ? "" : customLayout.etContent.getText().toString();
            value = value == null ? "" : value;
            if (edTextString.equalsIgnoreCase(value)) {
                return;
            }
            customLayout.setValue(value);
        }
}

将属性value与event名为“valueAttrChanged”的InverseBindingListener进行绑定,监听value属性的Setter事件,做到双向绑定。

@InverseBindingAdapter(attribute = "value", event = "valueAttrChanged")
public static String getValue(CustomLayout customLayout) {
    return customLayout.etContent.getText().toString();
}

为EditText添加TextWatcher,监听内容变化,触发InverseBindingListener的onChange()方法。

@BindingAdapter(
        value = {"android:beforeTextChanged",
                "android:onTextChanged",
                "android:afterTextChanged",
                "valueAttrChanged"},
        requireAll = false)
public static void setTextWatcher(
        CustomLayout view,
        final TextViewBindingAdapter.BeforeTextChanged before,
        final TextViewBindingAdapter.OnTextChanged on,
        final TextViewBindingAdapter.AfterTextChanged after,
        final InverseBindingListener valueAttrChanged) {
    TextWatcher newWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            if (before != null) {
                before.beforeTextChanged(s, start, count, after);
            }
        }
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (on != null) {
                on.onTextChanged(s, start, before, count);
            }
            if (valueAttrChanged != null) {
                valueAttrChanged.onChange();
            }
        }
        @Override
        public void afterTextChanged(Editable s) {
            if (after != null) {
                after.afterTextChanged(s);
            }
        }
    };
    TextWatcher oldWatcher = ListenerUtil.trackListener(view, newWatcher, R.id.textWatcher);
    if (oldWatcher != null) {
        view.etContent.removeTextChangedListener(oldWatcher);
    }
    view.etContent.addTextChangedListener(newWatcher);
}

绑定方式

在xml中通过@={}的方式绑定Observable变量。为Observable变量添加Observable.OnPropertyChangedCallback获取更新后的数据。

 app:value="@={viewModel.observedValue}"
public ObservableField observedValue = new ObservableField<>("");

observedValue.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
    @Override
    public void onPropertyChanged(Observable sender, int propertyId) {
        String changeResult = observedValue.get();
    }
});

你可能感兴趣的:([Android] DataBinding自定义View双向绑定)