计算动态标题大小时在 reloadData 上重置滚动位置

问题描述

我有一个带有一些自定义逻辑的大 UIcollectionView,在它的标题我有一个 UICollectionView,滚动方向设置为水平。除此之外,我在该标题视图中还有其他标签。我像这样得到标题的动态高度:

func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,referenceSizeforHeaderInSection section: Int) -> CGSize {
    let indexPath = IndexPath(row: 0,section: section)
    let headerView = self.collectionView(collectionView,viewForSupplementaryElementOfKind: UICollectionView.elementKindSectionHeader,at: indexPath)
    
    let desiredWidth = collectionView.frame.width > 0 ? collectionView.frame.width : UIScreen.main.bounds.width
    return headerView.systemLayoutSizefitting(CGSize(width: desiredWidth,height: UIView.layoutFittingExpandedSize.height),withHorizontalFittingPriority: .required,// Width is fixed
                                                      verticalFittingPriority: .fittingSizeLevel) // Height can be as large as needed
}

高度计算正确,但是如果我滚动水平 collectionView 然后从代码中的某个地方调用 reloadData,它的滚动位置将被重置。 我知道这是由于 let headerView = self.collectionView(collectionView,at: indexPath) 这一行而发生的,但是有没有办法让动态标题高度和滚动不被重置?

解决方法

这个问题的解决方案是在出队时保留一个headerView的实例,然后在计算header的高度时重新使用它。

if let headerView = self.headerView {
   return headerView.systemLayoutSizeFitting(
                    CGSize(width: desiredWidth,height: UIView.layoutFittingExpandedSize.height),withHorizontalFittingPriority: .required,// Width is fixed
                    verticalFittingPriority: .fittingSizeLevel) // Height can be as large as needed
}
            
return CGSize(width: desiredWidth,height: 1)