前言
当我们使用了一段时间的DataBinding后,我们有时可能会遇到布局传值类型不匹配的问题,或者说需要把一些复用的东西抽离出来的需求,强大的DataBinding帮我们提供了许多的注解来解决这些问题。
栗子
网络图片加载
问题
如果,我们在不使用ImageFilterView的情况下去使用ImageView,我们去给ImageView实现一个圆角,可能用卡片,或者说用Glide库,但是这样通常我们需要在任何使用它的位置添加卡片,或者写对应Glide代码。
即便ImageFilterView可以解决圆角问题,但是网络图片加载它仍然无法解决,这时,我们就想能否有一些办法,让我们给控件自定义一些属性,然后直接给这些属性写代码,通过统一的代码来完成这些属性描述的行为。
BindingAdapter
BindingAdapter,是DataBinding提供的一个注解类,我们在方法的前面加上@BindingAdapter,就可以给控件添加自定义的属性,或者修改新增原有属性的方法。
比如,我们正常情况下,给一个图片使用背景,我们会用下面这种。
android:background="@color/color_primary"
当我们给类中的方法上添加@BindingAdapter后,就重写它或者改变它传入的值的类型,并且你可以在此基础上为你的方法添加方法体,来给这个属性添加对应的逻辑。
比如,这样,我们就覆盖了安卓原来android:background接受到int值时执行的代码,我们可以在这里加一些其他的逻辑,再设置它的背景,但一般我们不会这样,后面我们会介绍到另一种注解,但是这仅仅是一个例子,告诉你格式应该是什么样的。
@BindingAdapter({"android:background"})
public static video setBackground(Button button,int color) {}
这样说,可能比较抽象,我们来看看实际例子,学习如何使用它。
解决上面的问题
首先,我们需要明确的是,我们需要通过属性配置,来使得imageview加载网络图片,并且,我们还需要有一个属性可以改变imagview的圆角。
这里,我们定义一个类,叫做ImageViewAdapter。
public class ImageViewAttrAdapter { @BindingAdapter({"android:imageUrl", "android:imageRoundingRadius"}) public static void loadImage(ImageView imageView, String url, int imageRoundingRadius) { //设置图片上去,就不在多写了 //Glide设置图片圆角角 RoundedCorners roundedCorners = new RoundedCorners(imageRoundingRadius); RequestOptions options = RequestOptions.bitmapTransform(roundedCorners); Glide.with(imageView.getContext()) .load(url) .apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL)) .apply(options) .into(imageView); } @BindingAdapter({"android:imageUrl"}) public static void loadImage(ImageView imageView, String url) { //Glide设置图片圆角角度 Glide.with(imageView.getContext()) .load(url) //启用缓存数据 .apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL)) .into(imageView); } }
从上面的类我们看见,我们在ImageViewAdapter中定义了两个静态方法,同时,我们也加入了@BindingAdapter的注解,来看看,我们其中一个类同时定义了两个属性,分别是android:imageUrl和android:imageRoundingRadius,同时我们可以看到这个方法承接的参数,顺序是一一对应的,我们还注意到,第一个参数必须是我们需要组件的父类,比如,我们这里使用了ImageView,因此第一个参数的类型是ImageView。
后端颜色值使用问题
问题
最近,我遇到了一个问题,在加载用户页面时,后端会告诉我这个用户是不是会员,是会员的话,它的颜色值应该是什么,但是这个颜色值是16进制的字符串类型,比如#FFFFFF,因为我没办法确定这个颜色值会发生怎样的变化,因此,我只能处理这个后端的颜色值。
但是,textColor它接受的可不是字符串类型,实际上我有时候会直接用#XXXXXX,或者@color/xxxx,但它们都不是字符串类型。
如图,textColor应该接受的是color也就是int值。
但是我一开始是这样使用的。
android:textColor="@{UserCardBean.data.card.vip.status == 1 ? UserCardBean.data.card.vip.nickname_color : `#000000`}"
我利用status参数来展示用户的会员状态色,但是这样会报错,因为textColor无法接受字符串类型,这时我们就需要想个办法解决一下。
解决
相信你已经有办法来解决它了
public class TextBindingAdapter { @BindingAdapter(value = {"android:textColor"}) public static void setTextColor(TextView textView, String textColor) { int color = Color.parseColor(textColor); textView.setTextColor(color); } @BindingAdapter(value = {"html"}) public static void setTextHtml(TextView textView, String html) { textView.setText(Html.fromHtml(html)); } }
OK,这是一个办法,这样我们限制了控件,这样只能给TextView,让我们来看看另一种方法。
BindingConversion
@BindingConversion注解可以做到属性的类型转换,像是我们上面的这个问题,类型转换就很适合,因为我们不仅仅是给一个组件使用,可能很多组件都需要解决这个问题,那么我们写一次即可。
public class TextBindingAdapter { @BindingConversion public static int setTextColor(String textColor) { return Color.parseColor(textColor); } @BindingAdapter(value = {"html"}) public static void setTextHtml(TextView textView, String html) { textView.setText(Html.fromHtml(html)); } }
TextBindingAdapter,我们用@BindingConversion注解了一个方法,注意,这个方法的名字得是符合你在代码里设置字体颜色的方法名称,比如这里我们使用了setTextColor,而@BindingAdapter并不需要规范什么名称。
这样,我们就巧妙的解决了这个字符串值的问题。
结尾
我通过以上两个开发遇到的实际问题来说这两个注解,希望大家可以看明白,如果觉得哪里说的有问题,欢迎在评论区告诉我。
发表回复