问题描述
包含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<String> observedValue = new ObservableField<>("");
observedValue.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
@Override
public void onPropertyChanged(Observable sender, int propertyId) {
String changeResult = observedValue.get();
}
});