SwiftUI 沒有 TableView (feat. Refreshable)

戴萌
4 min readSep 20, 2021

APP 設計中最常出現列表UI ,過去UIKit 是靠 TableView 或是 Collection View 完成它,但是SwiftUI裡TableView 也不再叫作TableView 且 也沒有Collection View了

沒有系列第三篇 這次來談 SwiftUI 沒有 TableView

像TableView 這樣好用的UI 當然不可能完全消失在SwiftUI 裡,在SwiftUI 中它叫做List ,不過 List 也可以使用ScrollView + VStack 去實作 List 樣式。

List

先放個官方文件,文件裡面已經寫了很多使用方式

最簡單的使用方式就是

List {
Text("Blue")
Text("Red")
Text("Yellow")
}

或是使用ForEach 動態產生List item

List {
ForEach(items, id: \.self) { item in
Text(item)
}
}

ScrollView + VStack

利用ScrollView + VStack 也可以建置List

但若是要使用ScrollView 來建置List 的話,有幾個東西是要自己處理的

第一個是分隔線(Separator),想要多粗多細或根本不想要有分隔線都可以隨自己開心

第二個是Padding,上下左右的Padding 都需要自行設定

第三個是 Item Size,使用List會有預設的Item Size ,VStack 當然不會有這種東西,所以要自行設定

所以上面的程式碼就會長這樣

此外也不會有List 特有的 Bounce 效果,這就要看設計需求來決定要怎麼使用

在iOS 15之後終於新增了一個先前就很好用的功能就是 refreshable(action:)

List(items, selection: $multiSelection) { item in
ItemView (title: item.title, color: item.color)
}
.refreshable {
//action
items.append(ItemInfo(title: "Puple", color: Color.purple))
}

以上面範例程式是在執行Refresh的時候再多加一個Item

像Refresh 這個一般都會用在刷新畫面,通知都是再呼叫一次API取得新的資料,這時官方建議可以加上 await 等待取得資料之後再刷新UI

.refreshable {
await mailbox.fetch()
}

iOS 15之後也可以選擇將分隔線隱藏,寫法是 .listRowSeparator(.hidden)

List(items) { item in
ItemView(title: item.title, color: item.color)
.listRowSeparator(.hidden)
}

本文章的Demo 可以在Github下載

--

--