iosswiftuicollectionviewuicollectionviewcelluicollectionviewlayout

CollectionViewCell scrolls to wrong position


I have a collectionView that is pinned to the to of the view (shown in 1st photo) and it has isPagingEnabled = true. I also hide the navigationBar.

When the cv loads for the very first time, the cell incorrectly displays underneath the device's top notch (shown in 2nd photo).

When I scroll/page the cell displays itself correctly behind the notch (3rd photo).

If I scroll/page back up to the 1st cell it positions itself correctly (3rd photo). However if I then pull the cv down, the cell snaps back to the incorrect position (2nd photo).

I also notice when the cell is in the wrong position, if I tap it it scrolls itself to the correct position.

I tried this answer and this answer and neither worked. I called view.layoutIfNeeded() and collectionView.layoutIfNeeded() in the functions.

Why is the cell displaying itself incorrectly when the cv first loads and when I pull to refresh but when I page either up or down it displays correctly?

lazy var collectionView: UICollectionView  = {

    let layout = UICollectionViewFlowLayout()
    layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

    let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
    collectionView.translatesAutoresizingMaskIntoConstraints = false
    collectionView.delegate = self
    collectionView.dataSource = self
    collectionView.alwaysBounceVertical = true
    collectionView.showsVerticalScrollIndicator = false
    collectionView.backgroundColor = .white
    collectionView.register(HomeCell.self, forCellWithReuseIdentifier: homeCell)

    collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    collectionView.scrollIndicatorInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

    collectionView.isPagingEnabled = true

    return collectionView
}()

override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .white

    setCollectionViewAnchors()
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    navigationController?.setNavigationBarHidden(true, animated: false)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    let width = collectionView.frame.width
    let height = collectionView.frame.height

    return CGSize(width: width, height: height)
}

func setCollectionViewAnchors() {

    let homeIndicatorHeight: CGFloat = 34 // https://stackoverflow.com/a/56639186/4833705

    view.addSubview(collectionView)

    collectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
    collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
    collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -homeIndicatorHeight).isActive = true
}

1st photo, cv anchor, top is pinned to the very top of the view behind the notch.

enter image description here

2nd photo, cell displays incorrectly behind notch for very first time and when on the 1st cell, when pulling cv down it displays incorrectly.

enter image description here

3rd photo, cell displays correctly behind the notch when scrolling/paging

enter image description here


Solution

  • I found the answer here.

    I had to add this line to my collectionView:

    collectionView.contentInsetAdjustmentBehavior = .never