首页 > 解决方案 > 带有 UICollectionViewCompositionalLayout 的单行水平 UICollectionView 的不完整删除动画

问题描述

UICollectionView目前,我有一个水平的单行UICollectionViewCompositionalLayout

[All] [Calendar] [Home2] [Work3] [Work4] ... [Work8] [⚙]

,UICollectionView充当可滚动的 Tab 布局导航栏。

当用户切换到[⚙]页面时,他可以删除它之前的标签。在这种情况下,在第一次删除操作期间,选项卡[Work8]将被删除。

这是实现此目的的简单代码。


https://github.com/yccheok/ios-tutorial/blob/debug/TabDemo/TabDemo/ViewController.swift#L144

func debug() {
    if tabInfos.count < 2 {
        return
    }
    
    let index = tabInfos.count-2
    tabInfos.remove(at: index)
    let indexPath = getIndexPath(index)
    self.tabCollectionView.deleteItems(at: [indexPath])
    
    // TODO: Possible solution.
    /*
    self.tabCollectionView.reloadData()
    DispatchQueue.main.async() {
        let indexPath = self.getIndexPath(self.tabInfos.count-1)
        self.tabCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
        self.tabCollectionView.scrollToItem(at: indexPath, at: .right, animated: true)
    }
     */

    // Clear left/ right cached view controllers - https://stackoverflow.com/a/21624169/72437
    pageViewController.dataSource = nil
    pageViewController.dataSource = self

    // Don't forget to adjust the selection index.
    if index < self.selectedTabInfoIndex {
        selectedTabInfoIndex -= 1
    }
}

奇怪的结果

https://www.youtube.com/watch?v=Wzgb4QErUes(完整删除动画请参考此视频)

这是删除前的样子

在此处输入图像描述

视频中可以看到,删除后[Work8],左侧标签([Work3])是不可见的

在此处输入图像描述

我的预期结果是,[Work3]应该立即可见,无需用户采取任何额外行动。我需要点击UICollectionView,移动它,只有所有的标签会出现

在此处输入图像描述


我不喜欢使用reloadData, 因为

  1. 它不会保留 的滚动位置UICollectionView
  2. 它没有动画。

你知道这个奇怪的动画结果的根本原因是什么吗?

这是试用的完整源代码 - https://github.com/yccheok/ios-tutorial/tree/debug(文件夹 TabDemo)

标签: iosswiftuicollectionviewuikit

解决方案


您需要稍微不同地配置布局 - 使用显式配置而不是正交行为。

这里是固定部分。使用 Xcode 11.7 / iOS 13.7 测试

演示

private func layoutConfig() -> UICollectionViewCompositionalLayout {
    let configuration = UICollectionViewCompositionalLayoutConfiguration()
    configuration.scrollDirection = .horizontal
    return UICollectionViewCompositionalLayout(sectionProvider: { (sectionNumber, env) -> NSCollectionLayoutSection? in
        let itemSize = NSCollectionLayoutSize(widthDimension: .estimated(44), heightDimension: .fractionalHeight(1))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        let groupSize = NSCollectionLayoutSize(widthDimension: .estimated(44), heightDimension: .absolute(44))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        let section = NSCollectionLayoutSection(group: group)
        section.interGroupSpacing = 1
        return section
    }, configuration: configuration)
}

推荐阅读