一、开启DataBinding
//在build.gradle文件添加
android{
dataBinding{
enabled true
}
}
二、生成DataBinding布局
1、光标在布局文件的根布局-->点击Alt + Enter-->点击 “Convert to data binding layout”
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="100dp"
android:layout_height="100dp"/>
</LinearLayout>
</layout>
2、创建数据类
class Test{
var aa = "aaaaa"
var background: Int = 0
}
3、在data中声明变量及类全名
<data>
<variable
name="test"
type="com.lpf.myapplication.Test" />
</data>
4、可以通过导包方式简化类全路径;重名类通过设置别名导包
<data>
<import type="com.lpf.myapplication.Test"/>
<import
alias="TestAbc"
type="com.abc.content.Test"/>
<variable
name="test1"
type="Test" />
<variable
name="test2"
type="TestAbc" />
</data>
5、通过@{test1.aa}使用变量;通过@{test.aa,default=12345}设置默认值(默认值无需加引号,且只在预览视图显示)
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:text="@{test1.aa}"
android:textSize="18sp"
android:background="@{test1.background}"/>
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:text="@{test2.aa,default=12345}"
android:textSize="18sp"/>
6、include布局
<include
layout="@layout/layout_title"
bind:test="@{test}"/>
//layout_title.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="test"
type="com.hualala.myapplication.Test" />
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{test.aa}"/>
</LinearLayout>
</layout>
7、DataBinding不支持merge标签
三、设置数据
1、在activity中使用(DataBinding布局都会自动生成绑定类,其中绑定类命名规则:布局文件名首字母大写且省去下划线+Binding)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val dataBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
val test = Test()
test.aa = "aaaa"
test.background = ContextCompat.getColor(this, R.color.colorAccent)
dataBinding.test = test
}
注:另外绑定类还可以直接通过控件id获取控件
2、在fragment中使用
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val testFragmentBinding = DataBindingUtil.inflate<TestFragmentBinding>(inflater, R.layout.test_fragment, container, false)
return testFragmentBinding.root
}
3、recyclerview中使用
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val dataBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
//通过id获取recyclerview
dataBinding.recyclerViewId.layoutManager = LinearLayoutManager(this)
dataBinding.recyclerViewId.adapter = TestAdapter()
}
class TestAdapter : RecyclerView.Adapter<TestAdapter.TestViewHolder>(){
private val testList = arrayListOf<Test>()
init {
for (i in 1..5){
val test = Test()
test.aa = "第{$i}条"
testList.add(test)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TestViewHolder {
val binding = DataBindingUtil.inflate<ItemTestBinding>(LayoutInflater.from(parent.context), R.layout.item_test, parent, false)
return TestViewHolder(binding)
}
override fun getItemCount(): Int {
return testList.size
}
override fun onBindViewHolder(holder: TestViewHolder, position: Int) {
holder.mBinding.test = testList[position]
}
class TestViewHolder(binding: ItemTestBinding) : RecyclerView.ViewHolder(binding.root) {
val mBinding: ItemTestBinding = binding
}
}
四、数据绑定
基本类型ObservableBoolean、ObservableByte、ObservableChar、ObservableShort、ObservableInt、ObservableLong、ObservableFloat、ObservableDouble 以及 ObservableParcelable ,也可通过 ObservableField 泛型来申明其他类型,还可以通过ObservableArrayList、ObservableArrayMap使用集合类型。其中“@={test.aa}”可以实现双向绑定。
class Test{
val aa = ObservableField<String>()
val bb = ObservableInt()
val cc = ObservableArrayMap<String, Drawable>()
}
object MapKey {
const val background = "background"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val dataBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
var test = Test()
dataBinding.test = test
test.aa.set("标题")
test.bb.set(ContextCompat.getColor(this, R.color.colorAccent))
test.cc[MapKey.background] = ContextCompat.getDrawable(this, R.drawable.ic_launcher_background)
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="test"
type="com.hualala.myapplication.Test" />
<variable
name="key"
type="com.hualala.myapplication.MapKey" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{test.aa}"
android:textColor="@{test.bb}"
android:background="@{test.cc[key.background]}"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@={test.aa}"/>
</LinearLayout>
</layout>
五、事件绑定
方法参数和原生事件参数一致可以使用"@{presenter::onClickOne}",不一致可以通过Lambda表达式"@{()-> presenter.onClickTwo(test)}"
class MainPresenter {
fun onClickOne(view: View){
Toast.makeText(view.context, "11111", Toast.LENGTH_SHORT).show()
}
fun onClickTwo(test: Test){
Log.i("aa", "*******${test.aa.get()}")
}
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="test"
type="com.hualala.myapplication.Test" />
<variable
name="presenter"
type="com.hualala.myapplication.MainPresenter" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{test.aa}"
android:onClick="@{presenter::onClickOne}"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{test.aa}"
android:onClick="@{()-> presenter.onClickTwo(test)}"/>
</LinearLayout>
</layout>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val dataBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
var test = Test()
dataBinding.presenter = MainPresenter()
dataBinding.test = test
test.aa.set("按钮")
}
六、调用静态方法
class StringUtil {
companion object{
@JvmStatic//需要添加该注解,否则xml中找不到该方法
fun toUpperCase(string: String): String{
return string.toUpperCase()
}
}
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.hualala.myapplication.StringUtil"/>
<variable
name="test"
type="com.hualala.myapplication.Test" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{StringUtil.toUpperCase(test.aa)}"/>
</LinearLayout>
</layout>
七、运算符
- 算术 + - / * %
- 字符串合并 +
- 逻辑 && ||
- 二元 & | ^
- 一元 + - ! ~
- 移位 >> >>> <<
- 比较 == > < >= <= !=
- 三元 ?:
- 空合并 ?? ("@{test.aa ?? test.bb}"等价于“@{test.aa!=null?test.aa:test.bb}”)
八、BindingAdapter自定义属性
1、声明属性(静态方法,kotlin需要加@JvmStatic注解)
class ImageUtil{
companion object{
@JvmStatic
@BindingAdapter("url")
fun loadImage(imageView: ImageView, url: String){
Log.e("aa", "*********$url")
}
}
}
注:check that the adapter is annotated correctly and that the parameter type matches异常,需要在build.gradle中添加apply plugin: 'kotlin-kapt'
2、引用属性(bind可以自定义)
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<import type="com.hualala.myapplication.ImageUtil"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
bind:url='@{"http://test.png"}'/>
</LinearLayout>
</layout>
注:包含字符串外层需要用单引号,如 android:text='@{"字符串"}'
九、BindingConversion数据转换
同类型转换,如conversionString添加前缀;不同类型转换如conversionStringToDrawable
object ImageUtil{
@JvmStatic
@BindingAdapter("url")
fun loadImage(imageView: ImageView, url: String){
Log.e("aa", "*********$url")
}
//同类型转换
@JvmStatic
@BindingConversion
fun conversionString(str: String): String{
return "http://$str"
}
//不同类型转换
@JvmStatic
@BindingConversion
fun conversionStringToDrawable(str: String): Drawable{
return ColorDrawable(Color.parseColor(str))
}
}
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<import type="com.hualala.myapplication.ImageUtil"/>
<variable
name="test"
type="com.hualala.myapplication.Test" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background='@{"#FF0000"}'>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
bind:url='@{"test.png"}'/>
</LinearLayout>
</layout>
注:
(1)@BindingConversion比@BindingAdapter先执行
(2)@BindingConversion使用companion object方式定义静态方法,会报异常@BindingConversion is only allowed on public static methods conversionString(String),采用Object方式定义静态方法即可
十、资源引用
<resources>
<string name="test_to_test">%s to %s</string>
</resources>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{@string/test_to_test("a","b")}'/>