Lance Samaria
Lance Samaria

Reputation: 19572

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

Upvotes: 0

Views: 997

Answers (3)

zef_s
zef_s

Reputation: 55

I had a bug with when resizing a UICollectionView, the cell position became incorrect.

This helped display my cells correctly layoutSubviews() + selectItem() + reloadData()

func changeCollectionFrame() {
    myCollection.constant = self.view.frame.width
    self.myCollection.layoutIfNeeded()
    self.myCollection.layoutSubviews()
    self.myCollection.reloadData()

    // index - myIndexPath
    self.myCollection.selectItem(at: index, animated: false, scrollPosition: .centeredHorizontally)
    self.myCollection.reloadData()
}

Upvotes: 0

Lance Samaria
Lance Samaria

Reputation: 19572

I found the answer here.

I had to add this line to my collectionView:

collectionView.contentInsetAdjustmentBehavior = .never

Upvotes: 0

Hudi Ilfeld
Hudi Ilfeld

Reputation: 2045

Try to call layoutIfNeeded() in the viewWillAppear() method, like this:

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

Upvotes: 0

Related Questions