我的目标是将Material Slider视图与我的viewmodel的MutableLiveData进行双向数据绑定:
<com.google.android.material.slider.Slider
...
android:value="@={viewmodel.fps}"
...
/>
当然,这不起作用是因为在androidx.databinding库中没有Slider的数据绑定适配器。
[databinding] Cannot find a getter for <com.google.android.material.slider.Slider android:value> that accepts parameter type <java.lang.Integer>. If a binding adapter provides the getter, check that the adapter is annotated correctly and that the parameter type matches.
但是,它们为SeekBar提供了一个适配器:/androidx/databinding/adapters/SeekBarBindingAdapter.java
据我所知,双向数据绑定仅能与“progress”属性一起使用,而单向数据绑定需要两种属性:“onChanged”和“progress”。
我尝试为Slider适配SeekBarBindingAdapter:
@InverseBindingMethods({
@InverseBindingMethod(type = Slider.class, attribute = "android:value"),
})
public class SliderBindingAdapter {
@BindingAdapter("android:value")
public static void setValue(Slider view, int value) {
if (value != view.getValue()) {
view.setValue(value);
}
}
@BindingAdapter(value = {"android:valueAttrChanged", "android:onValueChange"}, requireAll = false)
public static void setOnSliderChangeListener(Slider view, final Slider.OnChangeListener valChanged, final InverseBindingListener attrChanged) {
if (valChanged == null)
view.addOnChangeListener(null);
else
view.addOnChangeListener((slider, value, fromUser) -> {
if (valChanged != null)
valChanged.onValueChange(slider, value, fromUser);
});
if (attrChanged != null) {
attrChanged.onChange();
}
}
@Override
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
}
它不是建筑物:
Could not find event android:valueAttrChanged on View type Slider
但为什么它会寻找valueAttrChanged,如果我只使用
android:value="@={viewmodel.fps}"
如果我在Slider类中找不到valueAttrChanged,该如何找到正确的属性添加到BindingAdapter中呢?
text
之所以有效,是因为它们具有内置的双向数据绑定属性。但是,材料滑块没有配置属性。根据这个 GitHub问题,Android材料组件不提供预配置的适配器。至于android:value
,我猜它与一些现有定义冲突了,但不知道确切的原因。 - Valeriy Katkovvalue
属性,它允许我们摆脱自定义的 setter 适配器。我还更新了示例存储库。如果您仍有疑问,请随时提问。 - Valeriy KatkovsetSliderListeners()
在视图初始化时只会被调用一次,你可以通过向函数中添加日志来进行检查。绑定适配器在绑定值发生变化时会被调用,但在双向数据绑定的情况下,valueAttrChanged
只会被初始化一次。至于android
命名空间,它是保留给内置的Android属性的,应用程序特定的属性应该使用'app'命名空间。我无法说这个规则是如何被AndroidX库绕过的,但AndroidX是Android SDK的一部分,所以我认为他们知道一些秘密 :) - Valeriy Katkov