前面几篇文字介绍了databinding的接入使用以及数据的绑定,都是在代码层进行处理,但是如果我们要对layout层进行控制,如何操作呢?接下来我们将介绍BindingAdapter和BindingConversion
绑定适配器,是 Jetpack DataBinding 中用来扩展布局 xml 属性行为的注解,容许你针对布局 xml 中的一个或多个属性进行绑定行为扩展。注解值可以是已有的 xml 属性,如 android:src
、android:text
等,也可以自定义属性然后在 xml 中使用。
BindingAdapter修饰的类写法如下
@JvmStatic
@BindingAdapter("android:text")
fun settext(text: TextView, txt: String) {
text.text = "saaaaa"
}
@BindingAdapter("android:text")
public static void setText(TextView textview,String msg){
textview.setText(msg)
}
随便起一个静态类,参数为:当前对象,后面跟参数类型,不太清楚参数类型,可以看TypedArray内部修饰的类型。
BindingAdapter修改的是属性,需要跟完成的xml属性名
注意:该方法没有返回值,方法名随意起,但是一旦拦截了某个属性,只要在xml中通过@{}设置的属性都会被拦截,切统一修改
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='@{"ABC"}' />
如:
data :android:text="@{name}"
用户定义:android:text='@{"name"}'
修改用户自定义,也就是扩展类型,这种往往是因为layout或者xml无法满足databind的机制,比如:图片加载,无法直接在xml直接处理
<ImageView
android:id="@+id/img_url"
android:layout_width="200dp"
android:layout_height="200dp"
bind:url="@{controll.url}" />
我们定义了一个url的扩展字段。bind就是xmlns:bind="http://schemas.android.com/apk/res-auto"
@BindingAdapter("url")
@JvmStatic
fun loadUrl(img: ImageView, url: String) {
Glide.with(img.context).asBitmap().load(url).into(img)
}
BindingAdapter直接写扩展字段名。
这样就完美的解决了imageview的如何在xml中下载图片了。
BindingConversion是类型转换,必须有返回值。这个用法和BindingAdapter的有些不同,有无返回值,且参数只能是一个,不用传view对象过来。由于BindingConversion的优先级比BindingAdapter高,所以在执行顺序时有限执行。
函数名随意,一个参数,加一个返回值
@JvmStatic
@BindingConversion
fun color(txt: String): Int {
if (txt.equals("红色"))
return Color.RED
return Color.BLACK
}
这里面的返回值是int型。
<Button
android:id="@+id/btn_adapter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='@{"测试"}'
android:textColor='@{"红色"}' />
所以我们在textColor通过字符来获取对应的色值。
由于BindingConversion优先级比BindingAdapter高,且函数处理都是批量处理
@JvmStatic
@BindingConversion
fun bbbb(txt: String): String {
return "bbbb变种${txt}"
}
只要是设置了字符型,引用data格式@{} 的view,在text都会被追加"bbbb变种",这也导致了在接下来的
@BindingAdapter("url")
@JvmStatic
fun loadUrl(img: ImageView, url: String) {
SuningLog.d("loadUrl==" + url)
if (url.startsWith("bbbb变种")) {
Glide.with(img.context).asBitmap().load(url.substring("bbbb变种".length)).into(img)
return
}
Glide.with(img.context).asBitmap().load(url).into(img)
}
上面这个方法,设置String,其实url已变修改了,会导致图片无法正常加载。
所以在使用的时候,要格外注意。如果你不熟悉就不要使用BindingConversion。因为BindingConversion看似很高级,但是如果业务复杂,驾驭不了可能导致BindingAdapter的值被修改。
有一种情况可以使用,就是过滤text的脏字。所以在开发过程中,我推荐使用BindingAdapter一个就足够了。BindingConversion虽然炫酷,但是我们可以通过静态类来完成。
什么是静态类?我会在接下来的文章中介绍在xml布局用引用静态变量写出处理数据。
在开发过程中,我也猜了很多坑,是因为java和kotlin的衔接以及语法的问题
Required DataBindingComponent is null in class MyBindAdapterImpl. A BindingAdapter in com.example.wiik.testdemo.databinding.BindAdapterUtil is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.
这个错误的引用是因为kotlin的静态类,在java中jvn无法识别。针对这个问题,kotlin已提供了解决方法,只要在方法上方通过JvmStatic注解一下即可
@JvmStatic
@BindingAdapter("android:src")
fun setSrc(img: ImageView, resid: Int) {
img.setImageResource(resid)
}
BindingConversion is only allowed on public static methods conversionString
因为BindingConversion 比BindingAdapter 优先级要高,在执行任务的时候,会比BindingAdapter先执行,会被覆盖,
但是在kotlin中,BindingConversion 必须在object静态类中执行,不能放到静态模块中
companion object,但是BindingAdapter的要求只要是静态即可。
所以如果使用BindingConversion 必须放到静态类中
BindingAdapter和BindingConversion 都是需是静态方法,但是由于BindingConversion 必须在静态类中,不能放在静态模块中
companion object{ }
·这种写法无法满足,所以,如果你弄不明白静态方法和静态类,直接把所有的方法都在放一个静态类中,这个类作为工具类使用即可。