具有UICollectionViewCompositionalLayout

问题描述

当前,我在水平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(有关完整的删除动画,请参阅此视频)

这是删除前的样子

enter image description here

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

enter image description here

我的预期结果是,[Work3]应该也立即可见,而无需用户采取任何其他措施。我需要点击UICollectionView,将其略微移动,只有所有选项卡都会出现

enter image description here


我宁愿不要使用reloadData

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

您是否知道这种奇怪的动画结果的根本原因是什么?

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

解决方法

您需要对布局进行一些不同的配置-使用显式配置而不是正交行为。

这是固定的部分。经过Xcode 11.7 / iOS 13.7的测试

demo

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)
}
,

它尚未绘制,因为当您单击Work8的删除时它不在视口中。这是iOS的典型情况。

您可以强制重画而不是reloadData

myViewOrComponent.setNeedsDisplay();
,

您可以尝试一下吗,在这里您可能需要处理可滚动的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)
}