雖然在 WWDC 2020 沒有介紹 SwiftUI 引入 Collection View 的消息,但這無阻 UICollectionView
新增強大的新功能。
iOS 13 時,在 CollectionViews
中引進 CompositionalLayouts
與 DiffableDataSources
,為 UICollectionView
的建構 Layout 以及 DataSources 帶來更多的彈性。
到了 iOS 14,CollectionView API 添加了三個新的 API,分別負責 Layout、DataSources、及 Cell,也就是構建 Collection View 的三個要素:
Lists
新增於CompositionalLayouts
裡,為CollectionViews
帶來類似UITableView
的樣式。UICollectionView.CellRegistration
讓你以完全不同的方式使用新 Configuration API 來配置 Cell。另外,還有一個新的UICollectionViewListCell
具體類別 (concrete class),在預設情況下為 cell 提供類似列表的內容樣式。- Diffable Data Source 包含了 Section Snapshots,允許以 Section 為基礎更新更多資料。這對於建立 Outlined Styled 這個 iOS 14 的新層次列表非常有用。
在下一個段落中,我們將探討前兩個新增的 API。來看看如何用 iOS 14 的新方法,在 UICollectionView
中構建 Layout 和 Cell 吧!
iOS 14 Cell 的配置與註冊
iOS 14 引進了全新的 Cell Configuration API,來配置我們的 CollectionView Cell 和 TableView Cell。
也就是說,我們不需要像以前一樣,直接在 UITableViewCell
或 UICollectionViewCell
上設定屬性。
新的 Configuration API 讓我們能夠使用一個內容配置,來設定 Cell 的內容與樣式,或是依據不同的狀態作更新:
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewCell, String> { cell, indexPath, name in
var content = UIListContentConfiguration.cell()
content.text = name
cell.contentConfiguration = content
}
在 UICollectionViews
裡,我們有新的 UICollectionViewListCell
。我們可以用以下方式,直接擷取它的預設配置:
var content = listCell.defaultContentConfiguration()
這樣一來,我們就能夠避免使用 Cell Identifiers、及過去我們寫來確保 Cell 有註冊的 if let
與 guard let
陳述句。
更重要的是,我們不再直接地存取 Cell 的 Label 與 Image 屬性,這使我們能夠建構出讓 TableView
、CollectionView
與自定義 Cell 都可以使用的配置。
除了 contentConfiguration
以外,我們也可以利用 backgroundConfiguration
來設定背景屬性,另外還有 leadingSwipeActionsConfiguration
與 trailingSwipeActionsConfiguration
讓我們能輕鬆地把類似 UITableView
的滑動行為,直接嵌入到 UICollectionView
Cell 實作。
我們剛剛建立的新 UICollectionView.CellRegistration
結構,在傳送到 dequeueConfiguredReusableCell
內部時會自動處理 Cell 的註冊,因此你不再需要使用 Identifiers 來註冊 Cell。
iOS 14 CollectionViews 的新列表 Layouts
上個段落我們提到 UICollectionViewListCell
,想必你也猜到我們在 Compositional Layouts 上有個新的列表 Layout。
要快速設定這個 Layout,我們只需要傳入 UICollectionViewListConfiguration
。除了以下的 Plain 樣式外,我們還可以把樣式設定為 grouped
、insetGrouped
、sideBar
、以及 sideBarPlain
:
let config = UICollectionLayoutListConfiguration(appearance: .plain)
let layout = UICollectionViewCompositionalLayout.list(using: config)
新的 Lists
支援 UICollectionView
的好處,是為我們提供了自適應 (self-sizing) Cell 的開箱即用 (out-of-the-box) 支援。
我們還可以按 Section 來建立列表,方法是傳入 Compositional Layout 裡的 NSCollectionSectionLayout.list
。
要在 UICollectionView
裡自定義列表的 header
與 footer
,就與我們在 UITableView
的做法有點不同。
你需要在列表的配置中,以下列方式調用 headerMode
或 footerMode
:
config.headerMode = .supplementary
config.footerMode = .supplementary
接著,你需要調用 Diffable Data Source 上的 supplementaryViewProvider
,來提供視圖。在其中,你可以設定 dequeueConfiguredReusableSupplementary
函數,並將它傳送至 Header 配置。
現在,讓我們整合上述的新功能(Cell Configuration API、List Layout 與 Registrations)。
我們已經在 UIViewController
中設定好簡單的 UICollectionView
,如下所述:
class ViewController: UIViewController {
var items = Array(0...100).map { String($0) }
var collectionView : UICollectionView!
private lazy var dataSource = makeDataSource()
override func viewDidLoad() {
super.viewDidLoad()
let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
let layout = UICollectionViewCompositionalLayout.list(using: config)
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
self.view.addSubview(collectionView)
//add autolayout constraints
collectionView.dataSource = dataSource
var snapshot = NSDiffableDataSourceSnapshot<String,String>()
snapshot.appendSections(["Section 1"])
snapshot.appendItems(items)
dataSource.apply(snapshot, animatingDifferences: true)
}
func makeDataSource() -> UICollectionViewDiffableDataSource<String, String> {
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, indexPath, name in
var content = cell.defaultContentConfiguration()
content.text = name
cell.contentConfiguration = content
}
return UICollectionViewDiffableDataSource<String, String>(
collectionView: collectionView,
cellProvider: { collectionView, indexPath, item in
collectionView.dequeueConfiguredReusableCell(
using: cellRegistration,
for: indexPath,
item: item
)
}
)
}
}
在模擬器上執行 App,你會看到以下的結果:
總結
我們來總結一下:
- iOS 14 引進了新的
CellRegistration
技術,不再需要使用 Cell Identifiers 來註冊 Cell。 - 新的 Configuration API 封裝了 Cell 的內容及背景視圖屬性。
UICollectionViewListCell
提供了一個預設配置,我們可以表情況作設定及更新。 - 在設定 Cell 配置的時候,我們可以直接做客製化設定,像是滑動動作、設定 Accessories 等,讓我們維持單一的 source。
UICollectionView
的新列表看起來像UITableView
,我們可以使用適當的 Header 及 Footer 指定 Layout 和配置(甚至可以 Section 為基礎),來輕鬆組成列表。
我們很快地將所學內容整合起來,以宣告式建構了一個簡單的 UICollectionView
。是時候向 Cell Item Identifier 說再見了!
在下篇文章中,我們將關注 iOS 14 的 Diffable Data Sources 有什麼新功能,請密切留意。本篇文章到此為止,謝謝你的閱讀。
特別鳴謝 Zack Shapiro。