一、介绍
如果你学习了我前面的六篇文章,基本能够熟悉的处理data binding在开发过程的大多数业务,但是由于layout中的数据不一定满足UI上的效果,正常都是提前处理好数据,如果我们在layout引入中事件、运算逻辑、资源、工具类?那么代码层会显的很自然和干净。
了解了layout可以引入这些后,我们应该期待一下这些类的在layout的布局中如何使用?
二、使用详解
1.运算符逻辑使用
支持在布局文件中使用以下运算符、表达式和关键字
- 算术 + - / * %
- 字符串合并 +
- 逻辑 && ||(&在xml表达是:&)
- 二元 & | ^(&在xml表达是:&)
- 一元 + - ! ~
- 移位 >> >>> <<
- 比较 == > < >= <=
- instanceof
- Grouping ()
- character, String, numeric, null
- Cast
- 方法调用
- Field 访问
- Array 访问 []
- 三元 ?:
目前不支持以下操作
- this
- super
- new
- 显示泛型调用
转义字符:
字符 | 转义字符 |
> | > |
< | < |
& | & |
" | " |
数据:
<data class="MyDataBindDetail"> <import type="android.text.TextUtils" /> <variable name="data1" type="String" /> <variable name="data2" type="String" /> <variable name="data3" type="String" /> <variable name="value" type="int" /> </data>
但是这里面我们不可能完全使用,从常用角度来列举一些
算术
+:android:text="@{String.valueOf(1+2)}"
-:android:text="@{String.valueOf(200-2)}"
/:android:text="@{String.valueOf(10/2)}"
*:android:text="@{String.valueOf((2*2))}"
%:android:text="@{String.valueOf(7%3)}"
字符连接:
+:android:text="@{ data1+data2+data3}"
其实在Impl会生成对应的逻辑:
&&运算:
android:text="@{String.valueOf(value>2 && value<6) }"
||运算:
android:text="@{String.valueOf(value>2 || value<6) }"
instanceof类型判断:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{data3+ " instanceof= "}" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{data3 instanceof String ? " String " : " notString "}" />
三目运算 ?:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{value> 2? " 大于 " : " 小于等于 "}" />
2.资源使用
资源目前支持string与dimens
string:只支持formate,或者单个引入,
<string name="txt1">你好%s%s%s</string>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{@string/txt1(data1,data2,data3)}" />
string需要指定正确的占位符(内容类型),不可使用{0},与Message.formate不一样
dimen:
支持逻辑运算
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{@string/txt1(data1,data2,data3)}" android:textSize="@{flag?@dimen/app_bar_height:@dimen/fab_margin}" />
3.静态类使用
在布局中,我们可以通过静态类完成逻辑的修改。这样会更加方便。但是在静态类中,布局文件不可以使用类中的静态模块。
object MyUtil {
fun text(txt: String): String {
if (txt.equals("zhang")) {
return "这不是老张嘛"
}
return "大家都是老王"
}
fun text(age: Int): String {
return "老王今年${age}岁"
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data class="ClassMethodUtil">
<import type="com.example.wiik.testdemo.databinding.util.MyUtil" />
<variable
name="name"
type="String" />
<variable
name="age"
type="int" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{MyUtil.INSTANCE.text(name)}" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{MyUtil.INSTANCE.text(age)}" />
</LinearLayout>
</layout>
静态的加入,可以简化大家在xml中复杂的逻辑计算。如果你不会使用布局中逻辑,对转义字符记不住可以通过静态类来处理。
注意:
布局中的类一定不能引用静态模块中的方法。错误
class MyUtil {
companion object{
fun text(txt: String): String {
if (txt.equals("zhang")) {
return "这不是老张嘛"
}
return "大家都是老王"
}
fun text(age: Int): String {
return "老王今年${age}岁"
}
}
}
4、类的方法调用
类的方法和静态类使用差不多,一个是被初始化好了,一个是直接使用的。但是如果一些人使用MVVM的时候,喜欢把一些逻辑抽取在一个M层,也是一样使用。
,M层的内部类:
inner class MyMethodEntity(var context:Context){
fun getName(resId:Int):String{
return context.getString(resId)
}
fun getSizeName(name:String):String{
return "${name}长度为=${name.length}"
}
}
layout的处理如下:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data class="ClassMethodUtil">
<import type="com.example.wiik.testdemo.databinding.TestMethodActivity.MyMethodEntity" />
<variable
name="name"
type="String" />
<variable
name="age"
type="int" />
<variable
name="entity"
type="MyMethodEntity" />
<variable
name="resId"
type="int" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{entity.getName(resId)}" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{entity.getSizeName(name)}" />
</LinearLayout>
</layout>
这样也是借助于类提供的方法处理。
5、事件绑定
在android中,事件是一个动作的发生,特别是View,提供了各种事件的捕获,通过屏幕的传感捕获到再处理,传递底层,处理成对应的事件。
- android:onClick
- android:onLongClick
事件的绑定,可以不用通过在代码中通过set来完成,但是绑定也要按原来事件方法来完成。
例如:
android:onClick
object MyUtil {
fun onClick(view: View) {
Toast.makeText(view.context, "我点击l ", Toast.LENGTH_SHORT).show()
}
}
xml布局中引入:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{MyUtil.INSTANCE.onClick}"
android:text="点击onClick" />
解释:
如果是参数只有当前对象,可以不传,直接引用
如果有返回值:
fun onLongClick(view: View): Boolean {
Toast.makeText(view.context, "我点击2 ", Toast.LENGTH_SHORT).show()
return false
}
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onLongClick="@{MyUtil.INSTANCE.onLongClick}"
android:text="onLongClick" />
原生:
public interface OnLongClickListener {
boolean onLongClick(View v);
}
public interface OnClickListener {
void onClick(View v);
}
注意:
自定义事件,参数和返回值一定要和系统匹配,否则会报错。
自定义事件可以在M层内部类中,也可以在任何类中,只要方法负责自定义类都可以使用
6、Null Coalescing
??:如果第一个参数不为null,将会取第一个,否则取第二个值。
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{name??entity.getName(resId)}"
/>
三、总结
通过上面的介绍,我们可以掌握了逻辑、事件、工具类在layout使用。这样我们可以很方面在布局中处理一些事情。