上一篇在 xml 寫了簡單的 TextView 的 text 和 onClick 事件
那麼其他屬性該怎麼使用呢,在 xml 裡的語法和 Java、Kotlin 不一樣,有幾點特別注意
可以在 xml 使用三元運算式
ex.
判斷 viewModel 裡的變數 isLoading,是 true 就 View.VISIBLE,反之則 View.GONE
app:visibility="@{viewModel.isLoading ? View.VISIBLE : View.GONE}"
但如果要寫多行數的 if else 就沒辦法了,只能回到 java code 那邊去做。
判空
如果 user.nickname 是 null 則使用 user.name 賦值
android:text="@{user.nickname ?? user.name}"
要使用的話,必須轉成字串,這邊可以直接用程式語法轉成字串
ex.
android:text="@{String.valueOf(user.age)}"
或
android:text="@{user.age + ``}"
必須使用 ARGB 制,指定其所有的透明度和單色值,且前面不能加 "#"
ex.
android:textColor="@{title.color ?? 0xFF008577}"
data 的 type 如果是 List 的話要用 <> 包起來
但是 xml 檔不能寫 < 跟 >,要使用轉義字符換成 <
跟 >
ex.
<variable
name="strList"
type="java.util.List<String>" />
編譯時會報錯,要換成
<variable
name="strList"
type="java.util.List^<String^>" />
直接用中文會報錯,必須寫在 string.xml 再引用
ex.
錯誤
android:text="@{"名字"}"
正確
android:text="@{@string/name}"
如果 text 的地方是兩個 variable 拼起來的,沒辦法直接用空格之類的隔開
ex.
錯誤
android:text="@{user.firstName user.lastName}"
所以還是必須回到 string.xml,以上面這個例子,在 string.xml 就要寫成<string name="user_name">%1$s %2$s</string>
其中%1$s
代表的是第一個字串變量
代表的是空格%2$s
代表的是第二個字串變量
再回到 xml 把剛剛的錯誤代碼修改成
android:text="@{@string/user_name(user.firstName, user.lastName)}"
更詳細的語法可自行搜尋 轉義字符
這邊以 ArrayList 和 Map 做例子,其他種集合應該大同小異
首先把集合型態 import 進來
<data>
<import type="java.util.ArrayList" />
<import type="java.util.Map" />
<variable
name="strList"
type="ArrayList<String>" />
<variable
name="strMap"
type="Map<String,String>" />
</data>
使用:android:text="@{strMap.get(key)}"
這裡的 key 記得要用單引號包起來(Markdown 語法的關係這邊沒寫出來)
android:text="@{list.get(1)}"
或android:text="@{list[1]}"
不過我自己在實作 List 的時候一直失敗,連編譯都不能過
查了很多種集合的表示法都還是不行,最後自己用了一個我覺得還可行的方法
這是我的 model,有一個包 DataItem
的 List
data class AllPlayerData(
@SerializedName("data")
val data: List<DataItem>?
)
data class DataItem(
@SerializedName("first_name")
var firstName: String = ""
)
xml
<variable
name="allPlayerData"
type="com.guanhong.mvvmpractice.response.player.AllPlayerData" />
之後我花了很多時間做了各種嘗試
android:text="@{allPlayerData[0].firstName}"
android:text="@{allPlayerData.get(0).firstName}"
.
.
.
.
都無法成功,
最後我直接無視 List
把我要的 Type 直接 import 進來
<variable
name="dataItem"
type="com.guanhong.mvvmpractice.response.player.DataItem" />
修改剛剛的錯誤代碼
android:text="@{dataItem.firstName}"
最後在我程式碼裡面拿到數據後把我想要的那個 dataItem assign 給這個 binding 的 dataItem 就成功了
binding.dataItem = response.allPlayerData[0]
常聽到 Databinding 坑很多,今天算是體會到了呢
有任何問題或講得不清楚的地方歡迎留言和我討論。
更歡迎留言糾正我任何說錯的地方!
下一篇:Data Binding (四) BindingAdapter