Я реализую липкий заголовок UICollectionViewFlowLayout.Я могу растянуть заголовок при отслеживании, и он падает до минимальной высоты 40pt (плюс безопасная область) при отслеживании.
Проблема, с которой я столкнулся, заключается в том, что при отслеживании, когда смещение y в scrollView превышает высоту устройства, заголовок исчезает.Я могу только предположить, что это связано с тем, как происходит отключение ячеек в collectionView, но я не могу понять, как это остановить.
Вот код компоновки:
class StretchyHeaderLayout: UICollectionViewFlowLayout {
internal var headerHeight: StickyHeaderHeight! = StickyHeaderHeight(
collapsed: 40.0,
home: 250.0,
expanded: UIScreen.main.bounds.height)
fileprivate var cache = [UICollectionViewLayoutAttributes]()
override func prepare() {
super.prepare()
cache.removeAll()
guard let collectionView = collectionView else { return }
let sections = [Int](0..<collectionView.numberOfSections)
for section in sections {
let items = [Int](0..<collectionView.numberOfItems(inSection: section))
for item in items {
let indexPath = IndexPath(item: item, section: section)
if let attribute = layoutAttributesForItem(at: indexPath) {
cache.append(attribute)
}
}
}
if let header = layoutAttributesForSupplementaryView(ofKind: StretchyCollectionHeaderKind, at: IndexPath(item: 0, section: 0)) {
cache.append(header)
}
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let visibleAttributes = cache.filter { rect.contains($0.frame) || rect.intersects($0.frame) }
guard let collectionView = collectionView else { return visibleAttributes }
guard let header = cache.filter({ $0.representedElementKind == StretchyCollectionHeaderKind }).first else { return visibleAttributes }
header.frame = headerFrame(for: collectionView.contentOffset)
header.zIndex = 1000
return visibleAttributes
}
func headerFrame(for contentOffset: CGPoint) -> CGRect {
guard let collectionView = collectionView else { return .zero }
let x = CGFloat(0)
let y = contentOffset.y
let width = collectionView.frame.size.width
let height = max(min(headerHeight.home, headerHeight.expanded) - y, headerHeight.collapsed + UIScreen.safeArea.top)
print(min(headerHeight.home, headerHeight.expanded) - y.rounded(), max(min(headerHeight.home, headerHeight.expanded) - y, headerHeight.collapsed + UIScreen.safeArea.top).rounded(), headerHeight.collapsed + UIScreen.safeArea.top, height.rounded(), y.rounded())
return CGRect(x: x, y: y, width: width, height: height)
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
let attributes = super.layoutAttributesForItem(at: indexPath as IndexPath)?.copy() as! UICollectionViewLayoutAttributes
guard collectionView != nil else { return attributes }
attributes.frame.origin.y = headerHeight.home + attributes.frame.origin.y
return attributes
}
override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: StretchyCollectionHeaderKind, with: indexPath)
}
override var collectionViewContentSize: CGSize {
get {
guard let collectionView = collectionView else { return .zero }
let numberOfSections = collectionView.numberOfSections
let lastSection = numberOfSections - 1
let numberOfItems = collectionView.numberOfItems(inSection: lastSection)
let lastItem = numberOfItems - 1
guard let lastCell = layoutAttributesForItem(at: IndexPath(item: lastItem, section: lastSection)) else { return .zero }
return CGSize(width: collectionView.frame.width, height: lastCell.frame.maxY + sectionInset.bottom)
}
}
}
Для отладкиЯ пытался определить, не существует ли заголовок, через:
guard let header = cache.filter({ $0.representedElementKind == StretchyCollectionHeaderKind }).first else { return visibleAttributes }
Но он всегда проходит условие защиты.
Вот выходные данные оператора print, где заголовокисчезает на iPhone 10 (экран 812.0pt):
header offset | header height x3 | scrollView.contentOffset.y
-560.0 84.0 84.0 84.0 810.0
-561.0 84.0 84.0 84.0 811.0
-561.0 84.0 84.0 84.0 811.0
-561.0 84.0 84.0 84.0 811.0
-561.0 84.0 84.0 84.0 811.0
-561.0 84.0 84.0 84.0 811.0
-561.0 84.0 84.0 84.0 811.0
-562.0 84.0 84.0 84.0 812.0 <— disappears here
-562.0 84.0 84.0 84.0 812.0
-563.0 84.0 84.0 84.0 813.0
-564.0 84.0 84.0 84.0 814.0
-564.0 84.0 84.0 84.0 814.0