UICollectionViewFlowLayout для липкого заголовка - заголовок исчезает, когда смещение содержимого превышает высоту устройства - PullRequest
0 голосов
/ 29 сентября 2018

Я реализую липкий заголовок 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...