计算动态 header 大小时,滚动位置在 reloadData 上重置

Scroll position is reset on reloadData when calculating dynamic header size

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

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, viewForSupplementaryElementOfKind: UICollectionView.elementKindSectionHeader, at: indexPath) 这一行而发生的,但是有什么方法可以使动态 header 高度和滚动不被重置?

这个问题的解决方案是在出列时保留 headerView 的一个实例,然后在计算 header.

的高度时 re-use 它
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)