更改数据源时 UICollectionView 中的平滑动画
Posted
技术标签:
【中文标题】更改数据源时 UICollectionView 中的平滑动画【英文标题】:Smooth animation in UICollectionView when changing data source 【发布时间】:2019-04-03 20:14:26 【问题描述】:我有一个 UISegmentControl,用于切换 UICollectionView 的数据源。数据源是不同类型的对象。
例如,对象可能看起来像这样
struct Student
let name: String
let year: String
...
struct Teacher
let name: String
let department: String
...
而在包含 CollectionView 的视图中,会有这样的代码:
var students = [Student]()
var teachers = [Teachers]()
... // populate these with data via an API
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
if(segmentControl.titleForSegment(at: segmentControl.selectedSegmentIndex) == "Students")
return students?.count ?? 0
else
return teachers?.count ?? 0
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "personCell", for: indexPath) as! PersonCell
if(segmentControl.titleForSegment(at: segmentControl.selectedSegmentIndex)! == "Students")
cell.title = students[indexPath.row].name
cell.subtitle = students[indexPath.row].year
else
cell.title = teachers[indexPath.row].name
cell.subtitle = teachers[indexPath.row].subject
return cell
@IBAction func segmentChanged(_ sender: AnyObject)
collectionView.reloadData()
这会在两个数据源之间正确切换,但不会为更改设置动画。我试过这个:
self.collectionView.performBatchUpdates(
let indexSet = IndexSet(integersIn: 0...0)
self.collectionView.reloadSections(indexSet)
, completion: nil)
但这只是崩溃(我认为这是因为 performBatchUpdates 对删除什么和添加什么感到困惑)。
是否有任何简单的方法可以使这项工作顺利进行,而无需在 collectionView 中存储当前项目的单独数组,或者这是使这项工作顺利进行的唯一方法?
非常感谢!
【问题讨论】:
【参考方案1】:如果您的 Cell 的 UI 在不同的数据源中看起来相同,您可以在数据源上抽象一个 ViewModel,如下所示:
struct CellViewModel
let title: String
let subTitle: String
...
然后每次从 API 获取数据时,动态生成 ViewModel
var students = [Student]()
var teachers = [Teachers]()
... // populate these with data via an API
var viewModel = [CellViewModel]()
... // populate it from data above by checking currently selected segmentBarItem
if(segmentControl.titleForSegment(at: segmentControl.selectedSegmentIndex)! == "Students")
viewModel = generateViewModelFrom(students)
else
viewModel = generateViewModelFrom(teachers)
因此,您始终在 UICollectionView 中保留一个数据源数组。
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return viewModel?.count ?? 0
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "personCell", for: indexPath) as! PersonCell
cell.title = viewModel[indexPath.row].title
cell.subtitle = viewModel[indexPath.row].subTitle
return cell
@IBAction func segmentChanged(_ sender: AnyObject)
collectionView.reloadData()
然后试试你的 performBatchUpdates:
self.collectionView.performBatchUpdates(
let indexSet = IndexSet(integersIn: 0...0)
self.collectionView.reloadSections(indexSet)
, completion: nil)
【讨论】:
以上是关于更改数据源时 UICollectionView 中的平滑动画的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionview 在滚动时更改选择/禁用选择 - iOS
UICollectionView DataSource 方法未在 CoreData 更改时调用
设备方向更改时如何更改 UiCollectionView 单元格大小?
当 UICollectionView 更改布局时覆盖 UIAccessibilityLayoutChangedNotification