带有 UICollectionViewCompositionalLayout 的单行水平 UICollectionView 的不完整删除动画

Posted

技术标签:

【中文标题】带有 UICollectionViewCompositionalLayout 的单行水平 UICollectionView 的不完整删除动画【英文标题】:Incomplete delete animation for a single row horizontal UICollectionView with UICollectionViewCompositionalLayout 【发布时间】:2020-09-08 16:39:14 【问题描述】:

目前,我有一个水平单行 UICollectionViewUICollectionViewCompositionalLayout

[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://***.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,因为

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

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

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

【问题讨论】:

如果你在 git 上上传一个简单的可重现项目并将其链接到这里会很好 我已经发布了github.com/yccheok/ios-tutorial/releases/tag/debug(在文件夹github.com/yccheok/ios-tutorial/tree/debug(文件夹TabDemo)下) 我下载了你的演示项目,用 Xcode 12.0 beta 5 (12A8189h) 编译它,然后在 iPhone 11 Pro 模拟器上运行它。当我在“设置”选项卡中点击“删除”时,“工作 3”选项卡会正确显示。 【参考方案1】:

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

这里是固定部分。使用 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)

【讨论】:

我想我需要使用section.orthogonalScrollingBehavior = .continuous来实现水平滚动。我没有注意到这种configuration.scrollDirection = .horizontal 技术。谢谢你告诉我。【参考方案2】:

尚未绘制,因为当您单击 Work8 的删除时,它已超出视口。这对于 iOS 来说很典型。

你可以强制重绘而不是reloadData

myViewOrComponent.setNeedsDisplay();

【讨论】:

我尝试在UICollectionView 中调用setNeedsDisplay,在deleteItems 之后,这没有帮助。【参考方案3】:

你能试试这个吗,这里你可能需要处理可滚动的 contentSize 和 scrollPosition。

func debug() 
    if tabInfos.count < 2 
        return
    
    
    let index = tabInfos.count-2
    tabInfos.remove(at: index)
    var indexPath = getIndexPath(index)
    self.tabCollectionView.deleteItems(at: [indexPath])
    tabCollectionView.collectionViewLayout = layoutConfig()

    print(selectedTabInfoIndex)

    // Don't forget to adjust the selection index.
    if index < self.selectedTabInfoIndex 
        selectedTabInfoIndex -= 1
    
    indexPath = getIndexPath(selectedTabInfoIndex)
    self.selectTab(selectedTabInfoIndex)

【讨论】:

以上是关于带有 UICollectionViewCompositionalLayout 的单行水平 UICollectionView 的不完整删除动画的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 uuencode 的“sendmail”发送邮件,并带有主题

带有和不带有聚合的 sql 查询

如何翻转正面带有标签而背面带有另一个标签的视图 - 参见图片

CakePHP 如何处理带有/不带有 'id' 字段的 HABTM 表?

带有滚动的 Div 和带有绝对位置的内容

带有 RecyclerView 的 DialogFragment 比带有 Recyclerview 的 Fragment 慢