启用dataBinding
//在module的build.gradle中
apply plugin: 'kotlin-kapt'//必须
android{
//AS 4.0 以下,
dataBinding{
enabled true
}
//AS 4.1之后
buildFeatures{
dataBinding true
// for view binding :
// viewBinding true
}
}
UI改造
<layout>
<data class="这里可以定义自动生成的Binding类名称">
<import type="导入需要使用到的类 包名.类名 如:android.view.View"/>
<variable
name="与UI绑定的数据(可观察)"
type="androidx.databinding.ObservableField<String>" />
<variable
name="adapter"
type="androidx.recyclerview.widget.RecyclerView.Adapter" />
<variable
name="user"
type="com.cgf.demo.User" />
</data>
<!-- 原有的UI的xml布局放在layout标签内即可。data标签内存放用于xml的数据变量,类型 -->
<LinearLayout>
</layout>
variable
声明变量;
import
导入类型;
对于xml
的特殊符号需要转义类似&
绑定xml
与data
格式:@{}
、@={}
(双向绑定)
- 可用表达式、函数调用、属性参数
??
判空 ’ ’ 字段为空则默认使用 ?? 后面的内容
<TextView android:text="@{name??`Null of Name`}" />
?:
三目运算符
<TextView android:text="@{name==null? 'null':`nonull`}" />
@string/str_name
资源引用,可用占位符format
<string name="str_name_pre">姓名: %s,年龄%d</string>
<TextView android:text="@{@string/str_name_pre(user.name,user.age)}" />
+
拼接字符,使用**``**反引号
<TextView android:text="@{user.name+user.age}" />
default
设置默认值 ( 默认值仅供开发时界面预览,实际上是不显示的)
<TextView android:text="@{address,default=`beijing`}" />
include
绑定
被include的布局
<data>
<import type="com.cniao5.demo.BdTool"/>
<import type="com.cniao5.demo.BdToolKt"/>
<variable
name="user"
type="com.cniao5.demo.ItemBean" />
</data>
在include时把user属性赋值给被引入的user
<include
user="@{user}"
layout="@layout/item_rv" />
- 点击事件
可以是View的点击事件监听,或者调用其他外部方法
<Button
android:onClick="@{click}"
android:onclick="@{()->vm.click()}"
android:onclick="@{(v)->vm.click(v)}"
android:onclick="@{()->vm.click(context)}"
android:onclick="@{BindHelp::staticClick}"/>
代码中的使用
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding =
DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
//赋值
binding.apply {
user = User()
//click 对应xml中的click
click = View.OnClickListener {
user?.age = 22
user?.name = "改名啦"
}
}
RecyclerView Adapter中的使用
xml布局
<!-- RecyclerView中的使用-->
<layout>
<data>
<variable
name="adapter"
type="androidx.recyclerview.widget.RecyclerView.Adapter" />
</data>
<androidx.recyclerview.widget.RecyclerView
app:adapter="@{adapter}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="5"
tools:listitem="@layout/item_rv" />
</LinearLayout>
</layout>
适配器
class BdAdapter : RecyclerView.Adapter<BdAdapter.ItVH>() {
private val mList = mutableListOf<ItemBean>()
init {
for (i in 0..5){
mList.add(ItemBean(i,"艾特木 $i"))
}
}
class ItVH(private val binding: ItemRvBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(bean:ItemBean){
binding.info = bean
binding.executePendingBindings()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItVH {
return ItVH(ItemRvBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
override fun getItemCount() = mList.size
override fun onBindViewHolder(holder: ItVH, position: Int) {
holder.bind(mList[position])
}
}
@BindingMethods 和 BindingMethod 定自定义方法名称
一些属性具有名称不符的 setter 方法(比如TextView中就没有setText(arg : Int))。那么就可以自定义方法名称,使用 BindingMethods注释与 setter 相关联。注释与类一起使用,可以包含多个 BindingMethod注释,每个注释对应一个重命名的方法。
//xml code
<layout ……>
<data>
<variable
name="star"
type="int" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
……>
<com.kejiyuanren.jetpack.databinding.Number
app:number="@{star}"
……/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
//java code
@BindingMethods( //自定义方法名称集合,可以包含多个BindingMethod
value = [ //这是个数组
BindingMethod(
type = TextView::class, //要操作的属性属于哪个类
attribute = "number", //xml属性,使用(app:number=“20”)
method = "setTextNumber" //指定xml属性对应的set方法,参数类型要对应
)]
)
class Number @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : TextView(context, attrs, defStyleAttr) {
fun setTextNumber(number : Int) {
text = number.toString()
}
}
@BindingAdapter 作用和BindingMethod 类似
//value是一个数组 android:textColor 是在xml中的属性名字 可以自定义(使用app:或者nameSpace:)
@BindingAdapter(value = ["android:textColor"], requireAll = false)//如果不需要同时满足,requireAll设置为false
fun getColorId(view: TextView, type: Int) {//view 作用于的控件,type 属性值
val color = when (type) {
0 -> R.color.colorAccent
1 -> R.color.colorPrimaryDark
2 -> android.R.color.holo_red_dark
3 -> android.R.color.holo_orange_dark
else -> R.color.colorPrimary
}
view.setTextColor(view.context.resources.getColor(color))
}
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="info"
type="com.cgf.demo.ItemBean" />
</data>
<TextView
android:layout_width="300dp"
android:layout_height="wrap_content"
android:textColor="@{info.type}"/><!-- info.type是Int类型-->
</layout>
@BindingConversion 自定义转换
在某些情况下,需要在特定类型之间进行自定义转换。转换器是全局的,请谨慎使用。
//xml code
<layout ……>
<data>
<variable
name="show"
type="boolean" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
……>
<TextView
android:visibility="@{show}"
……/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
object DbAdapter {
@BindingConversion
@JvmStatic
fun setShowView(show: Boolean): Int {
return if (show) {
View.VISIBLE
} else {
View.GONE
}
}
}
以上有部分内容摘自这篇文章