我正在尝试关注this博文,试图让双向数据绑定适用于自定义组件(其中包含EditText的约束视图)。
我能够让两个标准的EditText组件与我的模型保持同步(两种方式),但是我在自定义组件中的更改流入我的模型时遇到了麻烦(尽管单向数据绑定有效) )。
我的模特:
public class Model extends BaseObservable {
private String value;
@Bindable
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
notifyPropertyChanged(company.com.databinding.BR.value);
}
public Model() {
value = "Value";
}
}
的活动:
@InverseBindingMethods({
@InverseBindingMethod(
type = CustomComponent.class,
attribute = "value",
method = "getValue")
})
public class MainActivity extends AppCompatActivity {
@BindingAdapter("value")
public static void setColor(CustomComponent view, String value) {
if (!value.equals(view.getValue())) {
view.setValue(value);
}
}
@BindingAdapter(
value = {"onValueChange", "valueAttrChanged"},
requireAll = false
)
public static void setListeners(CustomComponent view,
final ValueChangeListener onValueChangeListener,
final InverseBindingListener inverseBindingListener) {
ValueChangeListener newListener;
if (inverseBindingListener == null) {
newListener = onValueChangeListener;
} else {
newListener = new ValueChangeListener() {
@Override
public void onValueChange(CustomComponent view,
String value) {
if (onValueChangeListener != null) {
onValueChangeListener.onValueChange(view,
value);
}
inverseBindingListener.onChange();
}
};
}
ValueChangeListener oldListener =
ListenerUtil.trackListener(view, newListener,
R.id.textWatcher);
if (oldListener != null) {
view.removeListener(oldListener);
}
if (newListener != null) {
view.addListener(newListener);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setModel(new Model());
}
}
自定义组件:
public class CustomComponent extends ConstraintLayout {
private String value;
private EditText txt;
private TextWatcher textWatcher;
ValueChangeListener listener;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
if (txt != null) {
txt.setText(value);
}
}
public CustomComponent(Context context) {
super(context);
init(context);
}
public CustomComponent(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CustomComponent(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context) {
}
private void init(Context context, AttributeSet attrs) {
View.inflate(context, R.layout.custom_component, this);
txt = findViewById(R.id.txt_box);
final CustomComponent self = this;
textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
if (listener != null) {
listener.onValueChange(self, editable.toString());
}
}
};
txt.addTextChangedListener(textWatcher);
}
public void addListener(ValueChangeListener listener) {
this.listener = listener;
}
public void removeListener(ValueChangeListener listener) {
this.listener = null;
}
}
public interface ValueChangeListener {
public void onValueChange(CustomComponent view, String value);
}
我觉得那篇文章中的“挂钩事件”部分完全超出了我的想法;我真的只需要一个简单的setter和getter用于组件,因此无法理解在BindingAdapter中做了什么。在所有这些中,我认为这是我根本无法得到的这条线:
ValueChangeListener oldListener =
ListenerUtil.trackListener(view, newListener,
R.id.textWatcher);
答案 0 :(得分:1)
很抱歉,ListenerUtil令人困惑。这仅在您的组件支持多个侦听器时才有用。在这种情况下,您不能只设置一个新的侦听器,您必须删除旧的侦听器并添加新的侦听器。 ListenerUtil可以帮助您跟踪旧的侦听器,以便可以将其删除。在您的情况下,它可以简化:
@BindingAdapter(
value = {"onValueChange", "valueAttrChanged"},
requireAll = false
)
public static void setListeners(CustomComponent view,
final ValueChangeListener onValueChangeListener,
final InverseBindingListener inverseBindingListener) {
ValueChangeListener newListener;
if (inverseBindingListener == null) {
newListener = onValueChangeListener;
} else {
newListener = new ValueChangeListener() {
@Override
public void onValueChange(CustomComponent view,
String value) {
if (onValueChangeListener != null) {
onValueChangeListener.onValueChange(view,
value);
}
inverseBindingListener.onChange();
}
};
}
view.setListener(newListener);
}
然后将addListener()
替换为setListener()
,您不需要removeListener()
,因为您始终可以将监听器设置为null
。
您遇到的问题出现在您的组件中:
public String getValue() {
return value;
}
您将返回setter最后设置的值,而不是EditText中的值。要解决这个问题:
public String getValue() {
return txt.getText().toString();
}