是否可以使用 BindingAdapter 直接将事件绑定到 Observable 字段?

Is it possible to bind event to Observable field directly with BindingAdapter?

我正在为底部 sheet 编写绑定适配器,由 android-support-design 库提供。我想要实现的是将状态更改事件绑定到一个可观察字段,从而完全避免事件处理程序的胶水代码。

public class BottomSheetBindingAdapter {

    @BindingAdapter("behavior_onStateChange")
    public static void bindBottomSheetStateChange(final View view, final ObservableInt state) {
        final BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(view);
        if (behavior == null) throw new IllegalArgumentException(view + " has no BottomSheetBehavior");
        behavior.setBottomSheetCallback(new BottomSheetCallback() {

            @Override public void onStateChanged(@NonNull final View bottomSheet, final int new_state) {
                state.set(new_state);
            }

            @Override public void onSlide(@NonNull final View bottomSheet, final float slideOffset) {}
        });
    }
}

布局中XML:

bind:behavior_onStateChange="@{apps.selection.bottom_sheet_state}"

其中 "bottom_sheet_state" 是 ObservableInt 的一个字段。

然后编译器警告:Cannot find the setter for attribute 'bind:behavior_onStateChange' with parameter type int.似乎数据绑定编译器在匹配 BindingAdapter 时总是将 ObservableInt 字段视为 int。

我如何才能真正编写一个 BindingAdapter 来绑定事件处理程序以更改 Observable 字段,而无需视图模型中的胶水代码class?

您不能更改 BindingAdapter 中的 ObservableInt 值并期望它反映在视图模型中。你想要的是我s 双向绑定。由于没有开箱即用的 bottomSheetState 属性,我们需要通过创建 InverseBindingAdapter.

来创建双向绑定
@InverseBindingAdapter(
    attribute = "bottomSheetState",
    event = "android:bottomSheetStateAttrChanged"
)
fun getBottomSheetState(view: View): Int {
    return BottomSheetBehavior.from(view).state
}
@BindingAdapter(value = ["android:bottomSheetStateAttrChanged"], requireAll = false)
fun View.setBottomSheetStateListener(inverseBindingListener: InverseBindingListener) {
    val bottomSheetCallback = object : BottomSheetBehavior.BottomSheetCallback() {
        override fun onStateChanged(bottomSheet: View, @BottomSheetBehavior.State newState: Int) {
            inverseBindingListener.onChange()
        }

        override fun onSlide(bottomSheet: View, slideOffset: Float) {}
    }
    BottomSheetBehavior.from(this).addBottomSheetCallback(bottomSheetCallback)
}

顺便说一句,这是科特林代码。将此添加到顶层的任何 kt 文件中。然后你可以在 xml 中使用 like app:bottomSheetState="@={viewModel.bottomSheetState}"bottomSheetStateObservableInt.

现在您可以在 bottomSheetState 上观察底部 sheet 的状态变化。