0

我有2个部分。

顶部包含未选中的项目。

底部包含选中的项目。

当我选中/取消选中该项目时,我能够在两个部分之间实现漂亮的移动动画。

在此处输入图像描述

使用 Diffable Data Source 实现非常简单。

enum Section: Hashable {
    case unchecked
    case checked
}

func applySnapshot(_ animatingDifferences: Bool) {
    var snapshot = Snapshot()
    
    snapshot.appendSections([.unchecked])
    
    if !checkedChecklists.isEmpty {
        snapshot.appendSections([.checked])
    }
    
    snapshot.appendItems(uncheckedChecklists, toSection: .unchecked)

    if !checkedChecklists.isEmpty {
        snapshot.appendItems(checkedChecklists, toSection: .checked)
    }
    
    dataSource.apply(snapshot, animatingDifferences: animatingDifferences)
}

func checkedButtonClicked(_ checklistCell: ChecklistCell, _ checked: Bool) {
    guard let indexPath = collectionView.indexPath(for: checklistCell) else { return }
    
    let section = indexPath.section
    let item = indexPath.item
    
    if (section == 0) {
        // Unchecked
        uncheckedChecklists[item].checked = checked
    } else if (section == 1) {
        // Checked
        checkedChecklists[item].checked = checked
    } else {
        precondition(false)
    }
    
    applySnapshot(true)
}

但是,对于底部的标题,我不想显示“带有选中项目的标题” ,而是显示选中项目的计数。我修改代码如下。

enum Section: Hashable {
    case unchecked
    case checked(Int)
}

func applySnapshot(_ animatingDifferences: Bool) {
    var snapshot = Snapshot()
    
    snapshot.appendSections([.unchecked])
    
    if !checkedChecklists.isEmpty {
        snapshot.appendSections([.checked(checkedChecklists.count)])
    }
    
    snapshot.appendItems(uncheckedChecklists, toSection: .unchecked)

    if !checkedChecklists.isEmpty {
        snapshot.appendItems(checkedChecklists, toSection: .checked(checkedChecklists.count))
    }
    
    dataSource.apply(snapshot, animatingDifferences: animatingDifferences)
}

添加了一个附加代码以在标题中显示计数。

class ChecklistHeader: UICollectionReusableView {

    ...
    
    func update(_ section: NewChecklistViewController.Section) {
        switch section {
        case .unchecked:
            label.text = "Header with unchecked item"
            
        case .checked(let count):
            label.text = "Header with checked item \(count)"
    }
}

private func makeDataSource() -> DataSource {
    let dataSource = DataSource(
        ...
    )

    dataSource.supplementaryViewProvider = { collectionView, kind, indexPath in
        if kind == UICollectionView.elementKindSectionHeader {
            guard let checklistHeader = collectionView.dequeueReusableSupplementaryView(
                ofKind: kind,
                withReuseIdentifier: "header",
                for: indexPath) as? ChecklistHeader else {
                
                return nil
            }
            
            let sectionIdentifier = self.dataSource.snapshot().sectionIdentifiers[indexPath.section]
            if let section = sectionIdentifier as? Section {
                checklistHeader.update(section)
                
            }
            
            checklistHeader.delegate = self
            
            return checklistHeader
        } else if kind == UICollectionView.elementKindSectionFooter {
            ...
        }
        
        return nil
    }
    
    return dataSource
}

这是结果

在此处输入图像描述


如果你仔细观察

  1. 部分之间不再有移动动画。
  2. 这是因为,Diffable Data Source 将删除带有标识符的旧底部.check(1),并用带有新标识符的新底部替换.check(2)

我想知道,我怎样才能保留部分之间的移动动画,但能够更新标题的内容?

4

0 回答 0