Databinding使用总结

2021-09-29 15:18:35 浏览数 (1)

新项目使用Databining,已经完整开发一个版本,发现官方的文档以及网上资料都写的不够详细,所以做个整理,对于打算使用Databining的伙伴,应该会很有帮助

基础使用

我们先回顾下基础用法

定义一个data类,如下

代码语言:javascript复制
//定义一个用户信息data类
data class UserInfo(var age: Int, var name: String)

非常简单的一个类,在对应的XML中,就可以这样使用DataBinding了

代码语言:javascript复制
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="data"
            type="com.test.data.UserInfo" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@ id/tvName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{data.name}"
            android:textColor="@color/break_5"
            android:textSize="13dp" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

上面就是DataBinging的最简单用法了,下面结合具体例子,逐渐拓展到其他用法

条件使用

我想TextView在年龄大于18岁的才展示,小于18岁的不展示,可以这样设置

代码语言:javascript复制
<TextView
    android:id="@ id/tvName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{data.name}"
    android:visibility="@{(data.age >=18 )?View.VISIBLE:View.GONE}" />
    android:textColor="@color/break_5"
    android:textSize="13dp" />

年龄大于18岁,textview颜色显示红色

代码语言:javascript复制
<TextView
    android:id="@ id/tvName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:textColor="@{(data.age >=18)?@android:color/red:@android:color/white}" />

比如年龄等于30岁,就不显示textview

代码语言:javascript复制
<TextView
    android:id="@ id/tvName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="@{(data.age == 30 )?View.INVISIBLE:View.VISIBLE" />

带字符串

  • 想显示的文案,固定增加一个‘姓名’字段,可以这样写
代码语言:javascript复制
<TextView
    android:id="@ id/tvName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:text='@{"姓名:"   data.name}' />
  • 字符串本身有带有%d和%s的占位符 比如这个string <string name="sales_num">已售%d件</string> 在databinding里面的用法如下
代码语言:javascript复制
<TextView                                        
    android:id="@ id/tvName"                     
    android:layout_width="wrap_content"          
    android:layout_height="wrap_content"         
    android:background="@android:color/white"    
    android:text="@{@string/sales_num(data.age)}"
     />                                          
  • 在XML中对比字符串做条件判断 比如name的值为Jack,就不显示这个TextView,可以这样写
代码语言:javascript复制
<TextView
    android:id="@ id/tvStockNumber"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="@{data.name.equals(`Jack`)?View.INVISIBLE:View.VISIBLE}"
    android:text="@{data.name}"/>

点击事件

  • 常规的方式 外部传一个实现click方法的类 定一个viewModel,实现click方法:showLogout,方法参数就一个,就是view
代码语言:javascript复制
class AboutViewModel : ViewModel() {

    /**
     * 展示注销对话框
     */
    fun showLogout(view: View) {
        //do something
    }
}

然后把这个viewModel传给xml,实现这个点击方法

代码语言:javascript复制
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="viewModel"
            type="com.ygp.mro.viewmodels.AboutViewModel" />
    </data>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="52dp"
        android:text="@string/about_logout_account"
        android:onClick="@{viewModel::showLogout}" />
</layout>

这样的话,textview被点击后,会自动调用showLogout方法

  • 通用的点击方法 有个点击方法,很多页面都在使用,比如我们的titleBar,有个返回按钮,点击后,都是关闭当前页面

我们先定义好这个方法,参数就是View,方法就是关闭当前activity

代码语言:javascript复制
object BindingHelper {
    /**
     * 关闭当前activity
     */
    @JvmStatic
    fun bindFinishActivity(view: View) {
        val context = view.context
        if (context is FragmentActivity) {
            context.finish()
        }
    }
}

然后在xml的data中import这个类,就可以设置这个onClick事件了

代码语言:javascript复制
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <import type="com.ygp.mro.base.common.BindingHelper" />
    </data>

    <ImageView
        android:id="@ id/ivBack"
        android:layout_width="44dp"
        android:layout_height="44dp"
        android:foreground="?attr/selectableItemBackground"
        android:onClick="@{BindingHelper::bindFinishActivity}"
        android:src="@drawable/icon_arrows_left_large"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</layout>

这样的话,有N个页面,按钮的点击都是关闭当前activity,就可以在XML统一设置,其他地方不需要额外处理

  • 点击事件带参数 上面的DataBinding事件,都是只有一个View参数,有些场景,方法需要更多的参数,可以这样设置

先在viewModel中定义好方法

代码语言:javascript复制
fun goShopActivity(view: View, name: String) {     
    //do something 
}                                                      

这个方法,有一个view参数,还有一个name参数,在xml中,用如下的方式调用

代码语言:javascript复制
<TextView                                                                       
    android:id="@ id/shopName"                                                  
    android:layout_width="wrap_content"                                         
    android:layout_height="wrap_content" 
    android:maxLines="1"                                                        
    android:ellipsize="end"                                                     
    android:textSize="16dp"                                                     
    android:textColor="@color/break_1"        
    android:text="@{detail.shopName}"                                           
    android:onClick="@{(view)->viewModel.goShopActivity(view,data.name)}" 
    />                      

这样,点击的时候,name参数就也传过去了

多参数方法

  • 单个参数方法 比如,我需要定义一个通用的加载图片的方法,方法定义如下
代码语言:javascript复制
/**                                                                    
 * 加载图片                                                           
 */                                                                    
@BindingAdapter("setImageUrl")                             
@JvmStatic                                                             
fun bingImageUrl(imageView: ImageView, imgUrl: String?) {  
    if (imageView.context.isValid()) {                                 
        Glide.with(imageView.context).load(imgUrl ?: "")               
            .placeholder(glideHolderColor)                        
            .into(imageView)                                           
    }                                                                  
}                                                                      

然后在XML设置后,就会触发图片加载了

代码语言:javascript复制
<layout xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="imageUrl"
            type="String" />
    </data>

    <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
        app:setImageUrl="@{imageUrl}"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </ImageView>
</layout>
  • 多个参数的方法 还是图片加载,需要传圆角参数,不同的地方,圆角的弧度可以自定义设置

我们先定义方法如下

代码语言:javascript复制
/**                                                                               
 * 加载圆角图片                                                                         
 */                                                                               
@BindingAdapter("setImageUrlRound", "setImageRadius")                             
@JvmStatic                                                                       
fun bindImageViewUrlRound(imageView: ImageView, url: String?, radius: Int = 8) { 
    if (imageView.context.isValid()) {                                           
        Glide.with(imageView.context)                                             
            .load(url)                                                           
            .placeholder(ColorDrawable(glideHolderColor))                         
            .transform(RoundedCorners(DeviceUtils.dp2px(radius)))                 
            .into(imageView)                                                      
    }                                                                             
}                                                                                 

可以发现,BindingAdapter定义了两个属性名称,然后在xml中这样使用

代码语言:javascript复制
<ImageView                                        
    android:id="@ id/ivDetail"  
    android:layout_width="105dp"                  
    android:layout_height="105dp"    
    app:setImageRadius="@{5}"                     
    app:setImageUrlRound="@{item.imageUrl}" />    

把两个属性分别设置进去,这样加载图片,就可以传多个参数了

0 人点赞