iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 10
1
Mobile Development

Android Architecture Components 學習心得筆記系列 第 10

Day 10 Data Binding (三) 在 xml 裡的各種語法

  • 分享至 

  • xImage
  •  

上一篇在 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}"
  • 不能直接用 Boolean 和 Int 類型的值

要使用的話,必須轉成字串,這邊可以直接用程式語法轉成字串
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" />

之後我花了很多時間做了各種嘗試/images/emoticon/emoticon13.gif

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


上一篇
Day 9 Data Binding (二) 點擊事件
下一篇
Day 11 Data Binding (四) BindingAdapter
系列文
Android Architecture Components 學習心得筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言