How to make a collapsible header in collectionView as same as Facebook header?

Viewed 1097

Guys I need to make a collectionView header and it should work as when I scroll up the header collapses till specific point then the collapsing stops and the scroller keep scrolling as before collapsing, you can check this behavior in Facebook android app yet, I need to implement the same thing in iOS using swift, I have already tried to do so by using the delegate method of collectionView which is "scrollViewDidScroll" and this was myCode

func scrollViewDidScroll(_ scrollView: UIScrollView) {
     let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
        if scrollView.contentOffset.y > 199 {
            headerHeight = 101
            layout?.sectionHeadersPinToVisibleBounds = true
            collectionView.reloadData()
        } else if scrollView.contentOffset.y < 199 {
            headerHeight = 300
            layout?.sectionHeadersPinToVisibleBounds = false
            collectionView.reloadData()

        }
    }

PS: my original header height is 300, and the 199 is the portion which I need to hide after scrolling and the 101 value is the desired header height after scrolling

When I implemented this snippet of code , everything works fine but the problem is that when I reach the contentoffset.y of 199 , the cells of the collectionView will move up a little and when I scroll down < 199 the cells moves down , this quick move happens instantly, not smoothly which is bad UX. How to solve such a bug please?

1 Answers

To achieve this, You need to have a section header UICollectionReusableView

Storyboard layout

In UICollectionViewDelegateFlowLayout

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        
        switch kind {
        case UICollectionView.elementKindSectionHeader:
            guard
                let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "BlueHeaderCollectionReusableView", for: indexPath) as? BlueHeaderCollectionReusableView else {
                    fatalError("Invalid view type")
            }
            return headerView
        default:
            assert(false, "Invalid element type")
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        
        return CGSize(width: collectionView.frame.width, height: calculateHeight())
    }

To calculate height you can have a function as below

let min: CGFloat = 100
let max: CGFloat = 250

    func calculateHeight() -> CGFloat {
        let scroll = self.collectionView.contentOffset.y
        
        let heightTemp = max - scroll
        
        if  heightTemp > max {
            return max
        } else if heightTemp < min {
            return min
        } else {
            return heightTemp
        }
    }

Result

Output

Related