【问题标题】:Smooth animation in UICollectionView when changing data source更改数据源时 UICollectionView 中的平滑动画
【发布时间】: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 中存储当前项目的单独数组,或者这是使这项工作顺利进行的唯一方法?

非常感谢!

【问题讨论】:

    标签: ios swift animation uicollectionview


    【解决方案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)
    

    【讨论】:

      猜你喜欢
      • 2012-10-27
      • 1970-01-01
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 2018-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多