DataBinding自定义adapter

DataBinding支持使用自定义的方法来处理View。

自动检测自定义方法

假设现在有一个自定义View,其中有一个自定义方法setMyViewBgColor。

public class MyView extends AppCompatTextView {
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setMyViewBgColor(int color) {
        setBackgroundColor(color);
    }
}

在xml中


这时会发现,界面上View的背景变成了colorPrimary的颜色。

DataBinding会自动检测View中的set方法,如果与自定义属性的名称和参数一致,会进行调用。这个还是很方便的,省去了我们定义自定义属性的时间。

自定义关联的属性和方法,这样对方法命名就没有强制要求了

@BindingMethods({
        @BindingMethod(type = MyView.class,
                attribute = "bg",
                method = "setMyViewBgColor"),
})

public class MyView extends AppCompatTextView {


    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setMyViewBgColor(int color) {
        setBackgroundColor(color);
    }
}

自定义方法处理xml中的属性

DataBinding运行自定义方法,对应xml中的自定义属性。下面以图片加载为例

首先创建一个工具类,添加注释@BindingAdapter。value表示自定义属性的名称,从方法第二个参数开始一一对应。第一个参数表示哪种类型的View支持这个自定义方法。

public class ImageUtil {

    @BindingAdapter(value = {"image"})
    public static void loadImage(ImageView imageView, String url) {
        ImageLoader.get().loadImage(imageView, url);
    }
}


这样,网络图片就成功加载出来了。

这种方式也支持多个参数

@BindingAdapter(value = {"image","round"}, requireAll = false)
public static void loadImage(ImageView imageView, String url, boolean round) {
    if (round) {
        ImageLoader.get().loadImage(imageView, url, ImageOptions.option().circleCrop().build());
    } else {
        ImageLoader.get().loadImage(imageView, url);
    }
}

requireAll表示是否所有参数都必须填


这样加载出来的就是圆形图片

实际上,通过这种方式,可以解决使用Glide加载图片时,无法在xml中定义属性的问题,通过预定义各种参数,可以将Glide所有支持的属性,在xml中实现。

监听拓展

DataBinding可以对View原有的监听进行拓展。这里举两个例子

  • 支持在xml中调用任意类的方法处理OnTextChanged事件。
  • 防止多次点击的OnClick实现。

case 1

定义一个处理android:onTextChanged的方法。

public class AdapterUtils {

    @BindingAdapter("android:onTextChanged")
    public static void setTextChangedListener(EditText editText, final OnTextChangedListener listener) {
        if (listener != null) {
            TextWatcher textWatcher = new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    listener.onTextChanged(s.toString());
                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            };
            TextWatcher oldWatcher = ListenerUtil.trackListener(editText, textWatcher, R.id.textWatcher);
            if (oldWatcher != null) {
                editText.removeTextChangedListener(oldWatcher);
            } else {
                editText.addTextChangedListener(textWatcher);
            }
        }
    }
}

第二个参数是我们自定义的一个接口。DataBinding只支持单一方法的接口,因此自定义了一个新的接口。

public interface OnTextChangedListener {
    void onTextChanged(String text);
}
public class MainActivity extends AppCompatActivity {

    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.setMainActivity(this);
    }


    public void onTextChanged(String str){
        Log.d("x","onTextChanged--->"+str);
    }

}


    

        

    

    

        

    

最终在text改变时,会输出当前的text。

这样看起来代码更多了。但实际上这个adapter可以是通用的,以后所有的OnTextChanged只需要在某个类中定义一个公共方法,并在xml中引用即可。

case 2

定义一个代理方法。使用工具方法判断是否在短时间内重复点击。

    @BindingAdapter("android:onClick")
    public static void setClickListener(View view, final View.OnClickListener listener){
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (Utils.isFastDoubleClick()){
                    return;
                }
                listener.onClick(v);
            }
        });
    }

工具方法

public class Utils {

    private static long lastClickTime;

    public static boolean isFastDoubleClick() {
        long time = System.currentTimeMillis();
        long timeD = time - lastClickTime;
        if (0 < timeD && timeD < 800) {
            return true;
        }
        lastClickTime = time;
        return false;
    }

}

在xml中调用方法

在MainActivity中定义

public void onButtonClick(){
    Log.d("x","onClick");
}

测试下来确实短时间内快速点击不会重复触发点击事件

总结

总体来说,DataBinding支持3种方式对xml中的属性进行拓展

  • View的自定义方法
    • set前缀自动识别
    • 手动绑定属性和自定义方法
  • Adapter自定义View的属性
    • 支持自定义属性名
    • 自定义处理属性的方法
    • 支持多个属性作为方法的参数
  • Adapter拓展View原有的监听
    • 只支持单个函数的接口
    • 可以实现对原有监听的拦截

你可能感兴趣的:(DataBinding自定义adapter)