前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Databinding使用总结

Databinding使用总结

作者头像
韦东锏
发布2021-09-29 15:18:35
8480
发布2021-09-29 15:18:35
举报
文章被收录于专栏:Android码农Android码农

新项目使用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}" />    

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-05-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android码农 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基础使用
  • 条件使用
  • 带字符串
  • 点击事件
  • 多参数方法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档