版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2021.01.25 星期一 |
前言
iOS中有關(guān)視圖控件用戶能看到的都在UIKit框架里面,用戶交互也是通過UIKit進(jìn)行的棍弄。感興趣的參考上面幾篇文章望薄。
1. UIKit框架(一) —— UIKit動力學(xué)和移動效果(一)
2. UIKit框架(二) —— UIKit動力學(xué)和移動效果(二)
3. UIKit框架(三) —— UICollectionViewCell的擴(kuò)張效果的實(shí)現(xiàn)(一)
4. UIKit框架(四) —— UICollectionViewCell的擴(kuò)張效果的實(shí)現(xiàn)(二)
5. UIKit框架(五) —— 自定義控件:可重復(fù)使用的滑塊(一)
6. UIKit框架(六) —— 自定義控件:可重復(fù)使用的滑塊(二)
7. UIKit框架(七) —— 動態(tài)尺寸UITableViewCell的實(shí)現(xiàn)(一)
8. UIKit框架(八) —— 動態(tài)尺寸UITableViewCell的實(shí)現(xiàn)(二)
9. UIKit框架(九) —— UICollectionView的數(shù)據(jù)異步預(yù)加載(一)
10. UIKit框架(十) —— UICollectionView的數(shù)據(jù)異步預(yù)加載(二)
11. UIKit框架(十一) —— UICollectionView的重用、選擇和重排序(一)
12. UIKit框架(十二) —— UICollectionView的重用呼畸、選擇和重排序(二)
13. UIKit框架(十三) —— 如何創(chuàng)建自己的側(cè)滑式面板導(dǎo)航(一)
14. UIKit框架(十四) —— 如何創(chuàng)建自己的側(cè)滑式面板導(dǎo)航(二)
15. UIKit框架(十五) —— 基于自定義UICollectionViewLayout布局的簡單示例(一)
16. UIKit框架(十六) —— 基于自定義UICollectionViewLayout布局的簡單示例(二)
17. UIKit框架(十七) —— 基于自定義UICollectionViewLayout布局的簡單示例(三)
18. UIKit框架(十八) —— 基于CALayer屬性的一種3D邊欄動畫的實(shí)現(xiàn)(一)
19. UIKit框架(十九) —— 基于CALayer屬性的一種3D邊欄動畫的實(shí)現(xiàn)(二)
20. UIKit框架(二十) —— 基于UILabel跑馬燈類似效果的實(shí)現(xiàn)(一)
21. UIKit框架(二十一) —— UIStackView的使用(一)
22. UIKit框架(二十二) —— 基于UIPresentationController的自定義viewController的轉(zhuǎn)場和展示(一)
23. UIKit框架(二十三) —— 基于UIPresentationController的自定義viewController的轉(zhuǎn)場和展示(二)
24. UIKit框架(二十四) —— 基于UICollectionViews和Drag-Drop在兩個APP間的使用示例 (一)
25. UIKit框架(二十五) —— 基于UICollectionViews和Drag-Drop在兩個APP間的使用示例 (二)
26. UIKit框架(二十六) —— UICollectionView的自定義布局 (一)
27. UIKit框架(二十七) —— UICollectionView的自定義布局 (二)
28. UIKit框架(二十八) —— 一個UISplitViewController的簡單實(shí)用示例 (一)
29. UIKit框架(二十九) —— 一個UISplitViewController的簡單實(shí)用示例 (二)
30. UIKit框架(三十) —— 基于UICollectionViewCompositionalLayout API的UICollectionViews布局的簡單示例(一)
31. UIKit框架(三十一) —— 基于UICollectionViewCompositionalLayout API的UICollectionViews布局的簡單示例(二)
32. UIKit框架(三十二) —— 替換Peek and Pop交互的基于iOS13的Context Menus(一)
33. UIKit框架(三十三) —— 替換Peek and Pop交互的基于iOS13的Context Menus(二)
34. UIKit框架(三十四) —— Accessibility的使用(一)
35. UIKit框架(三十五) —— Accessibility的使用(二)
36. UIKit框架(三十六) —— UICollectionView UICollectionViewDiffableDataSource的使用(一)
37. UIKit框架(三十七) —— UICollectionView UICollectionViewDiffableDataSource的使用(二)
38. UIKit框架(三十八) —— 基于CollectionView轉(zhuǎn)盤效果的實(shí)現(xiàn)(一)
39. UIKit框架(三十九) —— iOS 13中UISearchController 和 UISearchBar的新更改(一)
40. UIKit框架(四十) —— iOS 13中UISearchController 和 UISearchBar的新更改(二)
41. UIKit框架(四十一) —— 使用協(xié)議構(gòu)建自定義Collection(一)
42. UIKit框架(四十二) —— 使用協(xié)議構(gòu)建自定義Collection(二)
43. UIKit框架(四十三) —— CALayer的簡單實(shí)用示例(一)
44. UIKit框架(四十四) —— CALayer的簡單實(shí)用示例(二)
45. UIKit框架(四十五) —— 支持DarkMode的簡單示例(一)
46. UIKit框架(四十六) —— 支持DarkMode的簡單示例(二)
47. UIKit框架(四十七) —— 自定義Calendar Control的簡單示例(一)
48. UIKit框架(四十八) —— 自定義Calendar Control的簡單示例(二)
49. UIKit框架(四十九) —— UIVisualEffectView原理和簡單使用(一)
50. UIKit框架(五十) —— UIVisualEffectView原理和簡單使用(二)
開始
首先看下主要內(nèi)容:
在本教程中痕支,您將學(xué)習(xí)如何在單個
collection view
中創(chuàng)建列表,使用現(xiàn)代單元配置(cell configuration)
以及配置多個section snapshot
蛮原。內(nèi)容來自翻譯卧须。
接著看下寫作環(huán)境:
Swift 5, iOS 14, Xcode 12
下面就一起來看正文啦。
在iOS 14中儒陨,Apple為UICollectionView
引入了新特性花嘶。Lists使您可以在UICollectionView
中包括類似UITableView
的部分。現(xiàn)代單元配置Modern Cell Configuration使注冊和配置collection view cell
更加容易蹦漠。并且,Section Snapshots允許UICollectionView
中包含多個section
隘击,其中每個section
可以具有不同的布局埋同。
在本教程中,您將學(xué)習(xí)如何:
- 使用
UICollectionLayoutListConfiguration
創(chuàng)建一個可擴(kuò)展列表list
哟冬。 - 使用
Modern Cell Configuration
來配置UICollectionView cell
。 - 使用
Section Snapshots
可將多個節(jié)(section)
添加到UICollectionView
错敢。
注意:本教程假定您熟悉Apple在iOS 13中引入的
UICollectionViewDiffableDataSource
和UICollectionViewCompositionalLayout
。如果您以前從未使用過它們咽块,請查看Collection View and Diffable Data Source and Modern Collection Views with Compositional Layouts。
事不宜遲亭罪,該開始了!
在Xcode
中打開啟動項(xiàng)目箩祥。構(gòu)建并運(yùn)行。
您會看到一個空的Pet Explorer
屏幕盲泛。 它是Get a Pet
應(yīng)用程序的一部分,該應(yīng)用程序顯示可供收養(yǎng)的寵物村视。 您將基于此應(yīng)用程序構(gòu)建。 在最終版本中杠氢,您可以瀏覽寵物類別并選擇一個寵物以查看其詳細(xì)信息。 然后因悲,當(dāng)您找到喜歡的寵物時晃琳,可以點(diǎn)擊Adopt以領(lǐng)養(yǎng)該寵物。
完整的應(yīng)用程序的Pet Explorer
屏幕顯示可用和已收養(yǎng)的寵物:
注意可愛的狗Diego
誊涯。完成本教程后,您將成為該虛擬小狗的驕傲擁有者取逾。
打開Xcode
。瀏覽項(xiàng)目晴埂。當(dāng)應(yīng)用啟動時,它使用PetExplorerViewController
作為根視圖控制器琅锻,將導(dǎo)航控制器設(shè)置為初始視圖控制器。打開Main.storyboard
選中該設(shè)置。
打開PetExplorerViewController.swift
以瀏覽此文件郁油。 PetExplorerViewController
的collectionView
為空。稍后案站,您將使用代表寵物和寵物類別的列表項(xiàng)來填充它蟆盐。
Pet.swift
具有與寵物有關(guān)的所有數(shù)據(jù)。
DataSource
類型別名是為了方便起見痹愚。稍后在配置UICollectionView
數(shù)據(jù)源時將使用它。
枚舉Section
代表.availablePets
和.adoptedPets
的UICollectionView
部分动壤。
最后,在PetExplorerViewController
擴(kuò)展程序中肩碟,您會找到pushDetailForPet(_:withAdoptionStatus :)
。當(dāng)用戶選擇一個項(xiàng)目時,此方法將顯示PetDetailViewController
吨拍。
打開PetDetailViewController.swift
伊滋。這是一個簡單的視圖控制器類笑旺,可顯示寵物的圖像,姓名和出生年月乌妙。
現(xiàn)在,您已經(jīng)探索了應(yīng)用程序的結(jié)構(gòu)荠察,接下來是時候了解UICollectionView
列表了。
What is a List?
list
是UICollectionView
中的table view
類似的視圖焕盟。您可以通過僅在少量代碼下將可配置的UICollectionViewCompositionalLayout
應(yīng)用于UICollectionView
的一section
來創(chuàng)建列表。
您可以配置列表以顯示分層數(shù)據(jù),并可以折疊和展開列表項(xiàng)或使其看起來類似于傳統(tǒng)的table view
沃于。如果您需要在應(yīng)用程序中使用table view
,則可以使用帶有UICollectionView API
的列表咨演,也可以使用傳統(tǒng)的UITableView
饵较。
在大多數(shù)情況下,列表list
更易于創(chuàng)建和配置打洼。
現(xiàn)在該創(chuàng)建您的第一個列表list
了。
Creating a List
您將創(chuàng)建一個顯示寵物類別的平面列表僻弹。這將是您不使用UITableView
的第一個table view
。對于平面列表,與UITableView
相比蚣抗,UICollectionView list
的優(yōu)勢可能不會立即顯現(xiàn)翰铡。稍后,當(dāng)您使列表可擴(kuò)展時迷捧,您會發(fā)現(xiàn)使用UICollectionView list
的真正好處。
注意:
UICollectionView
體系結(jié)構(gòu)在布局膛堤,表示形式和數(shù)據(jù)之間有清晰的分隔绿渣。本教程的示例代碼遵循這種模式。每次向Get a Pet添加新功能時誉帅,您都會添加一段代碼,首先用于布局郭膛,然后用于演示则剃,最后用于數(shù)據(jù)。
1. Configuring the Layout
在iOS 13
中己肮,Apple引入了UICollectionViewCompositionalLayout
,這是一種用于構(gòu)建復(fù)雜布局的新API。 在iOS 14
中鞍盗,Apple添加了:
static func list(using configuration: UICollectionLayoutListConfiguration) ->
UICollectionViewCompositionalLayout
這使您可以在一行代碼中創(chuàng)建list layout
,而無需了解UICollectionViewCompositionalLayout API
的詳細(xì)知識敷存。 您可以使用UICollectionLayoutListConfiguration
配置列表的外觀觅闽,顏色,分隔符孕锄,頁眉和頁腳。
現(xiàn)在該將其應(yīng)用于您的代碼了:
打開PetExplorerViewController.swift
恼除。 在帶有// MARK: - Functions
的行下方添加以下方法:
func configureLayout() {
// 1
let configuration = UICollectionLayoutListConfiguration(appearance: .grouped)
// 2
collectionView.collectionViewLayout =
UICollectionViewCompositionalLayout.list(using: configuration)
}
這將配置collectionView
的布局。 在這里舀患,您:
- 1) 創(chuàng)建具有
.grouped
外觀的configuration
现使。 這為您提供了一個看起來像table view
的布局配置顽冶。 - 2) 接下來,您將創(chuàng)建一個具有
list section
的UICollectionViewCompositionalLayout
间景,該節(jié)section
將使用該configuration
十拣。 您需要將此布局應(yīng)用于collectionView
。
如您所見,整個布局配置只有兩行代碼铛只。
通過添加以下內(nèi)容在viewDidLoad()
的末尾調(diào)用此方法:
configureLayout()
2. Configuring the Presentation
現(xiàn)在是時候?yàn)榱斜?code>list創(chuàng)建一個collection view cell
了非竿。 單元格顯示寵物類別承匣。 您將了解注冊單元格的新方法。
在第一個PetExplorerViewController
擴(kuò)展塊內(nèi)袍暴,添加:
// 1
func categoryCellregistration() ->
UICollectionView.CellRegistration<UICollectionViewListCell, Item> {
// 2
return .init { cell, _, item in
// 3
var configuration = cell.defaultContentConfiguration()
configuration.text = item.title
cell.contentConfiguration = configuration
}
}
這是您首次接觸modern cell registration and configuration
蚂会。 代碼是這樣的:
- 1)
categoryCellregistration()
為UICollectionViewListCell
類型的單元格和Item
類型的數(shù)據(jù)項(xiàng)創(chuàng)建單元格注冊。 這是注冊collection view cell
的現(xiàn)代方法。 - 2) 您創(chuàng)建單元格注冊枫慷,并傳入一個閉包來配置單元格。 當(dāng)
cell
需要渲染時調(diào)用閉包顿颅。 - 3) 然后配置
cell
斩跌。 寵物類別在item.title
中可用柬批。 如果您不了解正在發(fā)生的事情众旗,請不要擔(dān)心岁忘。 本教程的整個章節(jié)都涉及現(xiàn)代單元配置(modern cell configuration)
燃观。
在配置數(shù)據(jù)源時未舟,您將調(diào)用categoryCellregistration()
术瓮。
3. Configuring the Data
您已為collection view
配置了布局和單元格雕擂。 現(xiàn)在冰更,您需要一種機(jī)制,可以基于collection view
的基礎(chǔ)數(shù)據(jù)創(chuàng)建這些單元格归斤。 這就是數(shù)據(jù)源的來源酝碳。
將以下方法添加到PetExplorerViewController
中:
func makeDataSource() -> DataSource {
// 1
return DataSource(collectionView: collectionView) {
collectionView, indexPath, item -> UICollectionViewCell? in
// 2
return collectionView.dequeueConfiguredReusableCell(
using: self.categoryCellregistration(), for: indexPath, item: item)
}
}
這是您所做的:
- 1) 您創(chuàng)建并返回一個
DataSource
衡瓶,傳入collectionView
和一個閉包捂齐,該閉包將UICollectionViewCell
提供給數(shù)據(jù)源。 - 2) 在閉包內(nèi)部贵少,您要求
collectionView
使UICollectionViewCell
出dequeue
。 然后,您將單元格注冊作為參數(shù)傳遞序目,因此collectionView
將知道其必須出隊(duì)的單元格類型稽揭。 您剛才創(chuàng)建的categoryCellregistration()
包含單元配置的邏輯沮稚。
將以下屬性添加到PetExplorerViewController
:
lazy var dataSource = makeDataSource()
由于您在聲明中使用了lazy
定拟,因此在第一次需要collectionView
時會為其創(chuàng)建數(shù)據(jù)源。
您配置了collectionView
的布局,展示和數(shù)據(jù)缎除。 現(xiàn)在蕴忆,您將使用數(shù)據(jù)項(xiàng)填充collectionView
吟孙。
仍在PetExplorerViewController.swift
中矾屯,將以下方法添加到PetExplorerViewController
中:
func applyInitialSnapshots() {
// 1
var categorySnapshot = NSDiffableDataSourceSnapshot<Section, Item>()
// 2
let categories = Pet.Category.allCases.map { category in
return Item(title: String(describing: category))
}
// 3
categorySnapshot.appendSections([.availablePets])
// 4
categorySnapshot.appendItems(categories, toSection: .availablePets)
// 5
dataSource.apply(categorySnapshot, animatingDifferences: false)
}
此代碼使用可擴(kuò)散的數(shù)據(jù)源來更新list
的內(nèi)容罪针。 Apple在iOS 13
中引入了diffable data source
。該代碼尚無任何新的iOS 14
功能。 當(dāng)您使列表可擴(kuò)展并將section snapshots
添加到列表時瞒大,情況將會改變退渗。
使用applyInitialSnapshots()
可以:
- 1) 創(chuàng)建一個
categorySnapshot
,其中包含寵物類別名稱。 - 2) 然后為每個類別
category
創(chuàng)建一個項(xiàng)目Item
并將其添加到categories
中。 - 3) 將
.availablePets
附加到categorySnapshot
匈辱。 - 4) 然后將類別
categories
中的項(xiàng)目附加到categorySnapshot
的.availablePets
畸裳。 - 5) 將
categorySnapshot
應(yīng)用于dataSource
。
您已經(jīng)添加了一個部分section
膨处,并指明了屬于該部分的所有元素舟肉。
現(xiàn)在围苫,在viewDidLoad()
的末尾添加對applyInitialSnapshots()
的調(diào)用:
applyInitialSnapshots()
構(gòu)建并運(yùn)行
恭喜你饱亿! 這是您的第一個帶有列表的UICollectionView
。
列表list
支持與UITableView
樣式匹配的外觀:.plain配猫,.grouped
和.insetGrouped
幅恋。 您創(chuàng)建的列表具有.grouped
外觀。
iOS 14
具有用于將列表顯示為邊欄的新外觀:.sidebar
和.sidebarPlain
泵肄。 它們通常在拆分視圖(split view)
中用作主視圖捆交。
現(xiàn)在,您可以擴(kuò)展列表腐巢。
Making the List Expandable
現(xiàn)在是時候?qū)?code>pets添加到類別中了品追。
在這里,您將發(fā)現(xiàn)UICollectionView
列表的強(qiáng)大功能冯丙。 使用UITableView
肉瓦,您將不得不處理category cells and pet cell
上的點(diǎn)擊tap
,保持單元格的可見狀態(tài)和展開狀態(tài),并編寫顯示或隱藏寵物單元格的代碼泞莉。
使用UICollectionView
列表哪雕,您只需要提供類別和寵物的分層數(shù)據(jù)結(jié)構(gòu)。 該列表將處理其余的內(nèi)容鲫趁。 您很快就會發(fā)現(xiàn)斯嚎,僅需幾行代碼就可以實(shí)現(xiàn)很多目標(biāo)。
Pet.swift
包含所有寵物及其所屬類別的數(shù)據(jù)饮寞。 無需更改布局中的任何內(nèi)容孝扛,因此您將從展示開始。
1. Configuring the Presentation
之前幽崩,您為pet category
創(chuàng)建了一個單元格。 您了解了注冊單元格的新方法寞钥。 在這里慌申,您將執(zhí)行相同的操作,這次將為寵物創(chuàng)建一個cell
理郑。 單元格將顯示寵物的名字蹄溉。
在PetExplorerViewController.swift
中,添加:
func petCellRegistration() ->
UICollectionView.CellRegistration<UICollectionViewListCell, Item> {
return .init { cell, _, item in
guard let pet = item.pet else {
return
}
var configuration = cell.defaultContentConfiguration()
configuration.text = pet.name
cell.contentConfiguration = configuration
}
}
petCellRegistration()
與您之前添加的categoryCellregistration()
類似您炉。 您創(chuàng)建一個單元注冊并使用現(xiàn)代單元配置來配置該單元柒爵。 在這里,您使用defaultContentConfiguration()
赚爵,然后將寵物名稱分配為要顯示的文本棉胀。
在配置數(shù)據(jù)源時,您將調(diào)用petCellRegistration()
冀膝。
接下來唁奢,您可以通過向類別單元格添加outline disclosure accessory
來擴(kuò)展列表。 這表明一個項(xiàng)目可以展開和折疊窝剖。 當(dāng)您點(diǎn)擊一個類別時麻掸,列表將展開并顯示該類別的寵物。
在categoryCellregistration()
中赐纱,在cell.contentConfiguration = configuration
下方脊奋,添加:
// 1
let options = UICellAccessory.OutlineDisclosureOptions(style: .header)
// 2
let disclosureAccessory = UICellAccessory.outlineDisclosure(options: options)
// 3
cell.accessories = [disclosureAccessory]
在這里,您:
- 1) 創(chuàng)建要應(yīng)用于
disclosureAccessory
的options
疙描。 您使用.header
樣式使單元格可擴(kuò)展诚隙。 - 2) 然后,使用配置的
options
創(chuàng)建一個disclosureAccessory
淫痰。 - 3) 將
accessory
應(yīng)用于cell
最楷。 單元cell
可以具有多個附件,因此您可以在一個數(shù)組中添加discoveryAccessory
。
構(gòu)建并運(yùn)行籽孙。
outline disclosure
是可見的烈评,但是當(dāng)您點(diǎn)擊一個單元格時,什么也不會發(fā)生犯建。 為什么讲冠? 您尚未將寵物添加到其類別中。 接下來适瓦,您將要執(zhí)行此操作竿开。
2. Configuring the Data
接下來,您將學(xué)習(xí)如何將分層數(shù)據(jù)添加到列表中玻熙。 完成后否彩,您會看到列表自動支持折疊和展開單元格。
現(xiàn)在嗦随,調(diào)整數(shù)據(jù)源以將寵物細(xì)胞添加到其類別中列荔。
在makeDatasource()
中,替換為:
return collectionView.dequeueConfiguredReusableCell(
using: self.categoryCellregistration(), for: indexPath, item: item)
為
if item.pet != nil {
// 1
return collectionView.dequeueConfiguredReusableCell(
using: self.petCellRegistration(), for: indexPath, item: item)
} else {
// 2
return collectionView.dequeueConfiguredReusableCell(
using: self.categoryCellregistration(), for: indexPath, item: item)
}
一個item
可以代表一個類別或一個寵物枚尼。 這取決于pet
的值贴浙。 在此代碼中,collectionView
將dequeue
:
- 1) 如果
item.pet
不為nil
署恍,則為pet
的cell
崎溃。 - 2) 如果
item.pet
為nil
,則為category
的cell
盯质。
您已配置了展示寵物所需的一切袁串,但尚未添加任何寵物。 為此唤殴,您必須更新數(shù)據(jù)的初始快照般婆。
將body
替換為applyInitialSnapshots()
:
// 1
var categorySnapshot = NSDiffableDataSourceSectionSnapshot<Item>()
// 2
for category in Pet.Category.allCases {
// 3
let categoryItem = Item(title: String(describing: category))
// 4
categorySnapshot.append([categoryItem])
// 5
let petItems = category.pets.map { Item(pet: $0, title: $0.name) }
// 6
categorySnapshot.append(petItems, to: categoryItem)
}
// 7
dataSource.apply(
categorySnapshot,
to: .availablePets,
animatingDifferences: false)
要在類別和寵物之間建立層次關(guān)系,請執(zhí)行以下操作:
- 1) 創(chuàng)建類型為
NSDiffableDataSourceSectionSnapshot
的categorySnapshot
朵逝。 這是一個section snapshot
蔚袍。 使用section snapshot
,可以用分層結(jié)構(gòu)表示數(shù)據(jù)配名,例如帶有可擴(kuò)展項(xiàng)的輪廓啤咽。目前,這是有關(guān)section snapshot
的全部知識渠脉。 在本教程的后面宇整,您將了解有關(guān)section snapshot
的更多信息。 - 2) 然后芋膘,遍歷
Pet.Category.allCases
中的類別鳞青。 在循環(huán)中霸饲,將寵物添加到其類別中。 - 3) 創(chuàng)建一個
categoryItem
臂拓。 - 4) 將
categoryItem
追加到categorySnapshot
厚脉。 - 5) 然后,創(chuàng)建一個數(shù)組
petItems
胶惰,其中包含屬于當(dāng)前類別category
的所有寵物傻工。 - 6) 通過將
petItems
附加到當(dāng)前categoryItem
來創(chuàng)建類別和寵物之間的層次關(guān)系。 - 7) 將
categorySnapshot
應(yīng)用于dataSource
的.availablePets
孵滞。
構(gòu)建并運(yùn)行中捆。
點(diǎn)擊一個類別。列表將展開并顯示寵物名稱坊饶。很好泄伪!
現(xiàn)在是時候讓cell
看起來更好一點(diǎn)了。
What is Modern Cell Configuration?
如果您使用過UITableView
或UICollectionView
幼东,則習(xí)慣于通過直接設(shè)置單元格的屬性來對其進(jìn)行配置臂容。在iOS 14
中,單元配置可以完全與單元本身分離根蟹。
您創(chuàng)建類型為UIContentConfiguration
的cell content configuration
。然后糟秘,根據(jù)需要設(shè)置此內(nèi)容配置的屬性简逮。同樣,您可以創(chuàng)建類型為UIBackgroundConfiguration
的cell background configuration
尿赚。
結(jié)果是可重用的配置散庶,您可以將其應(yīng)用于您喜歡的任何cell
。
現(xiàn)在該看看它是如何工作的凌净!
Configuring the Cells
您剛剛學(xué)習(xí)了modern cell configuration
的理論”辏現(xiàn)在,您將通過添加代碼來更新pet cell
以顯示寵物的圖像和年齡冰寻,從而實(shí)施單元格內(nèi)容配置须教。在下一部分中,您將應(yīng)用cell background configuration
斩芭。
在petCellRegistration()
中轻腺,替換:
var configuration = cell.defaultContentConfiguration()
configuration.text = pet.name
cell.contentConfiguration = configuration
為
// 1
var configuration = cell.defaultContentConfiguration()
// 2
configuration.text = pet.name
configuration.secondaryText = "\(pet.age) years old"
configuration.image = UIImage(named: pet.imageName)
// 3
configuration.imageProperties.maximumSize = CGSize(width: 40, height: 40)
// 4
cell.contentConfiguration = configuration
在這里,您將看到實(shí)際的單元格內(nèi)容配置划乖。 您:
- 1) 使用默認(rèn)樣式創(chuàng)建類型
UIListContentConfiguration
的配置贬养。使用此配置,您將在一個單元格中設(shè)置圖像琴庵,文本和輔助文本误算。 - 2) 將寵物的數(shù)據(jù)應(yīng)用于配置仰美,包括寵物的圖像。
- 3) 設(shè)置圖像的尺寸儿礼。
- 4) 將
configuration
應(yīng)用于單元的contentConfiguration
咖杂。
構(gòu)建并運(yùn)行。
突然蜘犁,寵物看起來更可愛了翰苫。 您是否有動機(jī)領(lǐng)養(yǎng)個?
Adopting a Pet
最后这橙,您領(lǐng)養(yǎng)一只寵物奏窑。 Diego
正在等你接他!
首先屈扎,您將學(xué)習(xí)如何為單元創(chuàng)建和應(yīng)用后臺配置埃唯。 養(yǎng)有寵物的牢Cells
將具有背景色。 您將使用iOS 14
中引入的UIBackgroundConfiguration
鹰晨,它是現(xiàn)代單元配置的一部分墨叛。
入門項(xiàng)目已經(jīng)具有存儲被收養(yǎng)寵物的屬性:adoptions
。
在petCellRegistration()
和cell.contentConfiguration = configuration
下模蜡,添加:
// 1
if self.adoptions.contains(pet) {
// 2
var backgroundConfig = UIBackgroundConfiguration.listPlainCell()
// 3
backgroundConfig.backgroundColor = .systemBlue
backgroundConfig.cornerRadius = 5
backgroundConfig.backgroundInsets = NSDirectionalEdgeInsets(
top: 5, leading: 5, bottom: 5, trailing: 5)
// 4
cell.backgroundConfiguration = backgroundConfig
}
要為單元格提供彩色背景漠趁,請執(zhí)行以下操作:
- 1) 檢查寵物是否被收養(yǎng)。 只有收養(yǎng)的寵物才會有彩色背景忍疾。
- 2) 創(chuàng)建一個
UIBackgroundConfiguration
闯传,為listPlainCell
配置默認(rèn)屬性。 將其分配給backgroundConfig
卤妒。 - 3) 接下來甥绿,根據(jù)您的喜好修改
backgroundConfig
。 - 4) 將
backgroundConfig
分配給cell.backgroundConfiguration
则披。
您尚無法測試共缕。 您需要先養(yǎng)寵物。
入門項(xiàng)目有一個PetDetailViewController
士复。 該視圖控制器具有Adopt
按鈕图谷。 但是,如何導(dǎo)航到PetDetailViewController
判没?
您向?qū)櫸?code>cell添加一個disclosure indicator
蜓萄。 在petCellRegistration()
和cell.contentConfiguration = configuration
下,添加:
cell.accessories = [.disclosureIndicator()]
在這里設(shè)置單元格的disclosure indicator
澄峰。
現(xiàn)在嫉沽,當(dāng)您點(diǎn)擊寵物單元格時,您需要導(dǎo)航到Pet DetailViewController
俏竞。
將以下代碼添加到collectionView(_:didSelectItemAt :)
// 1
guard let item = dataSource.itemIdentifier(for: indexPath) else {
collectionView.deselectItem(at: indexPath, animated: true)
return
}
// 2
guard let pet = item.pet else {
return
}
// 3
pushDetailForPet(pet, withAdoptionStatus: adoptions.contains(pet))
當(dāng)您點(diǎn)擊pet cell
時绸硕,將調(diào)用collectionView(_:didSelectItemAt :)
堂竟。 在此代碼中,您:
- 1) 檢查所選
indexPath
處的item
是否存在玻佩。 - 2) 安全解包
pet
出嘹。 - 3) 然后,將
PetDetailViewController
推入導(dǎo)航堆棧咬崔。pushDetailForPet()
是入門項(xiàng)目的一部分税稼。
構(gòu)建并運(yùn)行。 尋找Diego
垮斯,然后點(diǎn)按單元格郎仆。
這是你的朋友Diego
兜蠕! 點(diǎn)擊Adopt
按鈕。
您已采用Diego
熊杨,然后導(dǎo)航回Pet Explorer
。 您會期望Diego
的單元格具有藍(lán)色背景晶府,但背景并非如此桂躏。 發(fā)生了什么?
數(shù)據(jù)源尚未更新沼头。 您現(xiàn)在就要做。
將以下方法添加到PetExplorerViewController
中:
func updateDataSource(for pet: Pet) {
// 1
var snapshot = dataSource.snapshot()
let items = snapshot.itemIdentifiers
// 2
let petItem = items.first { item in
item.pet == pet
}
if let petItem = petItem {
// 3
snapshot.reloadItems([petItem])
// 4
dataSource.apply(snapshot, animatingDifferences: true, completion: nil)
}
}
在此代碼中书劝,您:
- 1) 從
dataSource.snapshot()
中檢索所有items
土至。 - 2) 查找代表
pet
的item
并將其分配給petItem
购对。 - 3) 在
snapshot
中重新加載petItem
。 - 4) 然后將更新的
snapshot
應(yīng)用于dataSource
陶因。
現(xiàn)在確保收養(yǎng)寵物時調(diào)用updateDataSource(for :)
骡苞。
在petDetailViewController(_:didAdoptPet :)
中楷扬,添加:
// 1
adoptions.insert(pet)
// 2
updateDataSource(for: pet)
用戶收養(yǎng)寵物時,將調(diào)用此代碼烘苹。 在這里:
- 1) 將收養(yǎng)的
pet
插入adoptions
。 - 2) 調(diào)用
updateDataSource(for :)
霜定。 這是您剛創(chuàng)建的方法。
構(gòu)建并運(yùn)行望浩。 點(diǎn)擊Diego
。 然后磨德,在詳細(xì)信息屏幕上,點(diǎn)擊Adopt
酥宴。 向后瀏覽后搔弄,您會看到以下屏幕。
Diego
有藍(lán)色背景顾犹。 他現(xiàn)在是你的炫刷。
What is a Section Snapshot?
section snapshot
將UICollectionView
中單個section
的數(shù)據(jù)封裝起來。 這有兩個重要的好處:
- 1)
Section snapshot
使model hierarchical data
成為可能浑玛。 在實(shí)施帶有寵物類別的列表時,您已經(jīng)應(yīng)用了此功能极阅。 - 2)
UICollectionView
數(shù)據(jù)源每個section
可以有一個snapshot
,而不是整個collection view
的單個快照筋搏。 這使您可以將多個sections
添加到collection view
中厕隧,其中每個部分可以具有不同的布局和行為。
您將為收養(yǎng)的寵物添加一個section
吁讨,以了解其工作原理。
Adding a Section for Adopted Pets
您想在collectionView
中的單獨(dú)section
中創(chuàng)建收養(yǎng)的寵物列表排龄,其中包含您之前創(chuàng)建的寵物類別的可擴(kuò)展列表下方茶鹃。
1. Configuring the Layout
用以下命令替換configureLayout()
的body
:
// 1
let provider =
{(_: Int, layoutEnv: NSCollectionLayoutEnvironment) ->
NSCollectionLayoutSection? in
// 2
let configuration = UICollectionLayoutListConfiguration(
appearance: .grouped)
// 3
return NSCollectionLayoutSection.list(
using: configuration,
layoutEnvironment: layoutEnv)
}
// 4
collectionView.collectionViewLayout =
UICollectionViewCompositionalLayout(sectionProvider: provider)
這樣可以按部分section
配置collectionView
的布局艰亮。 在此代碼中挣郭,您:
- 1) 創(chuàng)建一個返回
NSCollectionLayoutSection
的閉包。 現(xiàn)在您有多個sections
侄非,并且此閉包可以根據(jù)sectionIndex
分別返回每個section
的布局流译。 在這種情況下,各section
的布局相同福澡,因此您無需使用sectionIndex
。您將閉包分配給provider
除秀。layoutEnv
提供有關(guān)布局環(huán)境的信息算利。 - 2) 為具有
.grouped
外觀的列表創(chuàng)建配置。 - 3) 返回具有給定
configuration
的section
的NSCollectionLayoutSection.list
效拭。 - 4) 使用
provider
作為sectionProvider
創(chuàng)建UICollectionViewCompositionalLayout
。 您將布局分配給collectionView.collectionViewLayout
慕的。
接下來挤渔,您將配置展示。
2. Configuring the Presentation
將以下方法添加到第一個PetExplorerViewController
擴(kuò)展塊中:
func adoptedPetCellRegistration()
-> UICollectionView.CellRegistration<UICollectionViewListCell, Item> {
return .init { cell, _, item in
guard let pet = item.pet else {
return
}
var configuration = cell.defaultContentConfiguration()
configuration.text = "Your pet: \(pet.name)"
configuration.secondaryText = "\(pet.age) years old"
configuration.image = UIImage(named: pet.imageName)
configuration.imageProperties.maximumSize = CGSize(width: 40, height: 40)
cell.contentConfiguration = configuration
cell.accessories = [.disclosureIndicator()]
}
}
此代碼將應(yīng)用于.adoptedPets
中的單元格。 它對您應(yīng)該看起來很熟悉俯邓。 與您在Configuring the Cells
中添加的petCellRegistration()
類似稽鞭。 現(xiàn)在,您將配置數(shù)據(jù)朦蕴。
3. Configuring the Data
在makeDatasource()
中弟头,替換:
return collectionView.dequeueConfiguredReusableCell(
using: self.petCellRegistration(), for: indexPath, item: item)
為
// 1
guard let section = Section(rawValue: indexPath.section) else {
return nil
}
switch section {
// 2
case .availablePets:
return collectionView.dequeueConfiguredReusableCell(
using: self.petCellRegistration(), for: indexPath, item: item)
// 3
case .adoptedPets:
return collectionView.dequeueConfiguredReusableCell(
using: self.adoptedPetCellRegistration(), for: indexPath, item: item)
}
使用此代碼涉茧,可以使數(shù)據(jù)源返回的單元格依賴于該section
。 在這里:
- 1) 安全地解包
section
伦连。 - 2) 返回
.availablePets
的petCellRegistration()
- 3) 返回
.adoptedPets
的enabledPetCellRegistration()
是時候?qū)⑦@些sections
添加到數(shù)據(jù)源中了钳垮。
在applyInitialSnapshots()
中,在方法的開頭插入以下代碼:
// 1
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
// 2
snapshot.appendSections(Section.allCases)
// 3
dataSource.apply(snapshot, animatingDifferences: false)
在此代碼中歧焦,您:
- 1) 創(chuàng)建一個新的
snapshot
肚医。 - 2) 將所有
sections
追加到snapshot
。 - 3) 將
snapshot
應(yīng)用于dataSource
忍宋。
構(gòu)建并運(yùn)行。 領(lǐng)養(yǎng)Diego
舵稠。
Diego
的背景是藍(lán)色入宦,所以您知道收養(yǎng)成功了。 但是您添加的section
在哪里落追?
該section
在那里涯肩,但為空。 您已將Diego
添加到了收養(yǎng)的寵物中病苗,但尚未將他插入數(shù)據(jù)源中。 這就是您現(xiàn)在要做的贷腕。
在petDetailViewController(_:didAdoptPet :)
中,在options.insert(pet)
的正下方泽裳,添加:
// 1
var adoptedPetsSnapshot = dataSource.snapshot(for: .adoptedPets)
// 2
let newItem = Item(pet: pet, title: pet.name)
// 3
adoptedPetsSnapshot.append([newItem])
// 4
dataSource.apply(
adoptedPetsSnapshot,
to: .adoptedPets,
animatingDifferences: true,
completion: nil)
使用此代碼,您:
- 1) 從數(shù)據(jù)源中檢索
.adoptedPets
的snapshot
胸囱。 您將其分配給adoptedPetsSnapshot
妹卿。 - 2) 為收養(yǎng)的
pet
創(chuàng)建一個新Item
,并將其分配給newItem
箕宙。 - 3) 將
newItem
追加到adoptedPetsSnapshot
铺纽。 - 4) 您將修改后的
acceptedPetsSnapshot
應(yīng)用于dataSource
的.adoptedPets
沥阳。
構(gòu)建并運(yùn)行。
起作用了其馏! Diego
在收養(yǎng)寵物部分。
您已經(jīng)了解了iOS 14
中UICollectionView
的許多改進(jìn)叛复,其中包括:
- 1) 使用
UICollectionLayoutListConfiguration
創(chuàng)建可擴(kuò)展list
。 - 2) 使用
Modern Cell Configuration
來配置UICollectionView
單元咖耘。 - 3) 使用
Section Snapshots
可將多個sections
添加到UICollectionView
撬码。
而您只接觸了表面。 有關(guān)更多詳細(xì)信息夫否,請查看WWDC 2020中的Advances in UICollectionView叫胁。
后記
本篇主要講述了基于
iOS14
的UICollectionView List
的創(chuàng)建,感興趣的給個贊或者關(guān)注~~~