brightec / CustomCollectionViewLayout

Custom layout for a collection view using horizontal and vertical scrolling with sticky rows and columns
MIT License
519 stars 123 forks source link

Stick header scroll down with other like header in tableview. #34

Open qhu91it opened 6 years ago

qhu91it commented 6 years ago

I try to make header stick when scrolling up and move down with other when contentOffset.y < 0. It works when scrolling slowly but when scroll so fast header move the wrong frame. Any suggestion help me out of this? Thanks.

qhu91it commented 6 years ago

Finally, I got this solution to work. define the value

let originY: CGFloat = 0
let floatingSectionOriginY = collectionView.contentOffset.y

If scrolling up use value from contentOffset.y to keep row is floating.

var selectedOriginY = originY
if floatingSectionOriginY >= originY {
    selectedOriginY = floatingSectionOriginY
}

Full code

override func prepare() {
        guard delegate != nil,
            let collectionView = collectionView,
            collectionView.numberOfSections > 0
            else { return }

        if itemAttributes.count != collectionView.numberOfSections {
            generateItemAttributes(collectionView: collectionView)
            return
        }

        let originY: CGFloat = 0
        let floatingSectionOriginY = collectionView.contentOffset.y
        let originX: CGFloat = 0
        let floatingSectionOriginX = collectionView.contentOffset.x

        for section in 0..<collectionView.numberOfSections {
            for item in 0..<collectionView.numberOfItems(inSection: section) {
                if section >= delegate.numberOfFirstRowFloat() 
                   && item >= delegate.numberOfFirstColumnFloat() {
                    continue
                }

                let attributes = layoutAttributesForItem(at: IndexPath(item: item, section: section))!

                if section < delegate.numberOfFirstRowFloat() {
                    var selectedOriginY = originY
                    if floatingSectionOriginY >= originY {
                        selectedOriginY = floatingSectionOriginY
                    }
                    var frame = attributes.frame
                    let size = itemsSize[item]
                    frame.origin.y = selectedOriginY + (size.height * CGFloat(section))
                    attributes.frame = frame
                }

                if item < delegate.numberOfFirstColumnFloat() {
                    var selectedOriginX = originX
                    if floatingSectionOriginX >= originX {
                        selectedOriginX = floatingSectionOriginX
                    }
                    var frame = attributes.frame
                    let prevItem = item - 1
                    if prevItem < 0 {
                        frame.origin.x = selectedOriginX
                    } else {
                        let size = itemsSize[prevItem]
                        frame.origin.x = selectedOriginX + (size.width * CGFloat(item))
                    }
                    attributes.frame = frame
                }
            }
        }
    }