Skip to content

绑定适配器

绑定适配器负责发出相应的框架调用来设置值。例如,设置属性值就像调用 setText() 方法一样。再比如,设置事件监听器就像调用 setOnClickListener() 方法。

提供自定义逻辑

框架提供的适配器

某些特性需要自定义绑定逻辑。例如,android:paddingLeft 特性没有关联的 setter,而是提供了 setPadding(left, top, right, bottom) 方法。使用 BindingAdapter 注释的静态绑定适配器方法支持自定义特性 setter 的调用方式。

Android 框架类的特性已经创建了 BindingAdapter 注释。 例如,以下示例展示了 paddingLeft 特性的绑定适配器,在androidx.databinding.adapters.ViewBindingAdapter

    @BindingAdapter({"android:paddingLeft"})
    public static void setPaddingLeft(View view, float paddingFloat) {
        final int padding = pixelsToDimensionPixelSize(paddingFloat);
        view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(),
                view.getPaddingBottom());
    }

参数类型非常重要。第一个参数用于确定与特性关联的视图类型,第二个参数用于确定在给定特性的绑定表达式中接受的类型。

自定义适配器

新建类BindingAdapterUtil,指定@BindingAdapter({"overPaddingLeft"})overPaddingLeft就是layout中可用的设置。

public class BindingAdapterUtil {

    @BindingAdapter({"overPaddingLeft"})
    public static void setOverPaddingLeft(View view, float paddingFloat) {
        final int padding = pixelsToDimensionPixelSize(paddingFloat) + 20; // fake padding!
        view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(),
                view.getPaddingBottom());
    }

    private static int pixelsToDimensionPixelSize(float pixels) {
        final int result = (int) (pixels + 0.5f);
        if (result != 0) {
            return result;
        } else if (pixels == 0) {
            return 0;
        } else if (pixels > 0) {
            return 1;
        } else {
            return -1;
        }
    }
}

参数类型非常重要。setOverPaddingLeft(View view, float paddingFloat)第一个参数用于确定与特性关联的视图类型,第二个参数用于确定在给定特性的绑定表达式中接受的类型。

layout中使用这个BindingAdapter,注意app:overPaddingLeft="@{model.paddingLeft}"

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="model"
            type="com.rustfisher.tutorial2020.databinding.data.BindingAdapterModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="16dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#f0f0f0"
            android:text="Rust Fisher. Padding left sample."
            app:overPaddingLeft="@{model.paddingLeft}" />
    </LinearLayout>
</layout>

运行起来可以看到TextView的paddingLeft会多一小截。

layout中如果不使用@{},比如填入数字,编译时报错Android resource linking failed

Android resource linking failed
/Users/rustfisher/Tutorial2020/app/build/intermediates/incremental/mergeDebugResources/stripped.dir/layout/act_data_binding_adapter_1.xml:15: error: attribute overPaddingLeft (aka com.rustfisher.tutorial2020:overPaddingLeft) not found.
error: failed linking file resources.

如果您希望在设置了任意特性时调用适配器,则可以将适配器的可选 requireAll 标记设置为 false。 例如下面ImageView的示例。

    @BindingAdapter(value={"imageUrl", "placeholder"}, requireAll=false)
    public static void setImageUrl(ImageView imageView, String url, Drawable placeHolder) {
      if (url == null) {
        imageView.setImageDrawable(placeholder);
      } else {
        MyImageLoader.loadInto(imageView, url, placeholder);
      }
    }

注意:出现冲突时,绑定适配器会替换默认的数据绑定适配器。