内容简介:绑定适配器的作用就是,调用比如,调用绑定适配器,可以让你决定给
绑定适配器的作用就是,调用 UI
框架层合适的方法,给 view
属性进行赋值。
比如,调用 setText()
方法给 TextView
的 text
属性赋值;调用 setOnClickListener()
方法,给 view
的 onClick
属性赋值。
绑定适配器,可以让你决定给 view
属性赋值调用哪个方法,还可以让你自己定制该方法的具体逻辑。
给 view
属性赋值
当数据发生变化时,绑定类必须调用 view
的合适的 set()
方法,给 view
属性赋值。这时候有三种选择:一种是让 Data Binding
库自己决定调用哪个方法;一种是明确指定调用哪个方法;一种是自己定义一个方法。
-
Data Binding
库自动选择
比如 view
有一个属性叫做 example
, Data Binding
库会试图去找一个 setExample(args)
的方法,这个方法接收的参数类型需要和绑定表达式的返回类型一致。注意,属性命名空间是不考虑的,寻找方法的唯一标准就是,方法名和参数类型。
比如,对于表达式 android:text="@{user.name}"
, Data Binding
库会寻找该 view
的 setText(args)
方法,如果 user.name
的类型是 String
,则寻找 setText(String args)
方法;如果 user.name
的类型是 Int
,则寻找 setText(Int args)
方法。
即使一个 view
在 android
命名空间没有对应的属性, Data Binding
库依然可以正常工作。比如, DrawerLayout
并没有 android:scrimColor
和 android:drawerListener
这些属性,却有 setScrimColor(int)
和 setDrawerListener(DrawerListener)
方法,这时我们就可以使用自定义命名空间的属性 app:scrimColor
和 app:drawerListener
:
<android.support.v4.widget.DrawerLayout android:layout_width="wrap_content" android:layout_height="wrap_content" app:scrimColor="@{@color/scrim}" app:drawerListener="@{fragment.drawerListener}"> 复制代码
- 明确指定要调用的方法
有时候 view
的属性名和 set()
方法名并不匹配。比如 ImageView
有一个 android:tint
属性,对应的方法名却是 setImageTintList(ColorStateList)
,这时我们可以使用 BindingMethods
注解, BindingMethods
用于注解一个类,它可以包含多个 BindingMethod
注解, BindingMethod
注解就声明了 view
属性要匹配哪个 set()
方法:
@BindingMethods(value = [ BindingMethod( type = android.widget.ImageView::class, attribute = "android:tint", method = "setImageTintList")]) 复制代码
上面示例表明了: ImageView
的 android:tint
属性,需要调用 setImageTintList()
方法。
- 自己定义一个方法
有时候 view
属性需要自定义绑定逻辑。比如 view
属性有 android:paddingLeft
属性却没有 setPaddingLeft(int)
方法,但是有 setPadding(int left, int top, int right, int bottom)
方法,这时候我们需要自定义逻辑。这时,我们使用 BindingAdapter
注解一个 static
方法,如下所示:
@BindingAdapter("android:paddingLeft") fun setPaddingLeft(view: View, padding: Int) { view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()) } 复制代码
上面的示例表明了: View
的 android:paddingLeft
的属性,会调用 view
的 setPadding(int left, int top, int right, int bottom)
。
注意,该方法的参数很重要,第一个参数指明了 view
的类型,第二个参数指明了绑定表达式的返回值是 Int
类型。
如果自定义的适配器和系统的适配器有冲突,自定义的适配器会覆盖系统的。
BindingAdapter
注解可以接收多个参数,如下所示:
@BindingAdapter("imageUrl", "error") fun loadImage(view: ImageView, url: String, error: Drawable) { Picasso.get().load(url).error(error).into(view) } 复制代码
<ImageView app:imageUrl="@{venue.imageUrl}" app:error="@{@drawable/venueError}" /> 复制代码
上述示例表明了: view
类型是 ImageView
,有两个属性 imageUrl
和 error
,这两个属性对应绑定表达式的返回类型分别是 String
和 Drawable
。
注意,只有当 ImageView
同时有 imageUrl
和 error
两个属性时,上述方法才会被调用。如果你希望 ImageView
有任一属性都可以调用,可以声明 requireAll = false
:
@BindingAdapter(value = ["imageUrl", "placeholder"], requireAll = false) fun setImageUrl(imageView: ImageView, url: String, placeHolder: Drawable) { if (url == null) { imageView.setImageDrawable(placeholder); } else { MyImageLoader.loadInto(imageView, url, placeholder); } } 复制代码
有时 BindingAdapter
可能需要属性的旧值,可以这么使用:
@BindingAdapter("android:paddingLeft") fun setPaddingLeft(view: View, oldPadding: Int, newPadding: Int) { if (oldPadding != newPadding) { view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()) } } 复制代码
@BindingAdapter("android:onLayoutChange") fun setOnLayoutChangeListener( view: View, oldValue: View.OnLayoutChangeListener?, newValue: View.OnLayoutChangeListener? ) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { if (oldValue != null) { view.removeOnLayoutChangeListener(oldValue) } if (newValue != null) { view.addOnLayoutChangeListener(newValue) } } } 复制代码
上述示例中,第二个参数是旧值,第三个参数是新值。
数据类型转换
- 自动转换
在绑定表达式中,表达式的返回值类型需要与对应的 set()
方法接收的参数类型一致,如果不一致我们需要在绑定表达式中进行转换,例如 android:text=@{user.age}
, user.age
返回值类型是 Int
, setText(String text)
接收的参数类型是 String
,此时我们就需要进行转换:
android:text=@{String.valueOf(user.age)} 复制代码
上述示例中:调用了 String.valueOf()
方法,把 Int
转换为了 String
。
- 自定义转换
有些场景是固定地在两种类型之间进行转换,这时候可以使用自定义转换。比如 view
的 android:background
属性接收 Drawable
类型的数据,但是在绑定表达式中使用的却是 Int
类型,如下所示:
<View android:background="@{isError ? @color/red : @color/white}" android:layout_width="wrap_content" android:layout_height="wrap_content"/> 复制代码
这时候, Int
需要转换为 Drawable
,我们可以使用 BindingConversion
注解一个静态方法,如下所示:
@BindingConversion fun convertColorToDrawable(color: Int) = ColorDrawable(color) 复制代码
注意,绑定表达式中的返回值类型必须是固定的,如下所示是错误的:
<View android:background="@{isError ? @drawable/error : @color/white}" android:layout_width="wrap_content" android:layout_height="wrap_content"/> 复制代码
上面示例中,绑定表达式的返回值类型是不确定的,可能是 Drawable
或者 Int
,这种使用方法是不行的。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ruby on Rails电子商务实战
Christian Hellsten、Jarkko Laine / 曹维远 / 人民邮电出版社 / 2008-4 / 49.00元
《Ruby on Rails电子商务实战》全面讲解了使用Ruby on Rails创建产品级应用程序的过程。书中通过演示构建网上书店的全过程,先后介绍如何使用如TDD的敏捷实践,启动一个项目并建立良好稳定的基础,如何深入Ruby on Rails,实现诸如将应用程序翻译成各种语言对产品进行调试等的普遍需求。其中用到的主要技术包括Ajax、聚合、设置标签和国际化等,还介绍了如何使用ActiveRec......一起来看看 《Ruby on Rails电子商务实战》 这本书的介绍吧!