'Collection view cell with horizontal inset does not remain centred when scrolled

Hey I have a collection view with the following scrolling behaviour:

enter image description here

The cells need to have a spacing of 16 pts between them and remain centered when scrolled. You can see in the demo only the first and last cell remain centred. My collection view width is the same width as the screen. Setup in viewDidLoad like so:

func setupCollectionView() {
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.showsHorizontalScrollIndicator = false
        collectionView.showsVerticalScrollIndicator = false
        collectionView.register(UINib(nibName: "SubtopicCollectionCell", bundle: nil), forCellWithReuseIdentifier: "SubtopicCollectionCell")
        let flowLayout = UICollectionViewFlowLayout()
        flowLayout.scrollDirection = .horizontal
        flowLayout.minimumLineSpacing = 16
        collectionView.isPagingEnabled = true
        collectionView.setCollectionViewLayout(flowLayout, animated: false)
    }

The various delegate methods as follows:

func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 5
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell: SubtopicCollectionCell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubtopicCollectionCell", for: indexPath) as! SubtopicCollectionCell
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: collectionView.frame.size.width * 0.78, height: collectionView.frame.size.height)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 0, left: 40, bottom: 0, right: 40)
    }

It's important that part of the next cell is displayed on the screen with the current cell centred (like the first and last cell in the demo). How do I achieve this behaviour?



Solution 1:[1]

You can achieve with following simple calculation in your collectionViewLayout function.

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {

    let cellWidth = CellWidth * CellCount
    let spacingWidth = CellSpacing * (CellCount - 1)

    let leftInset = (collectionViewWidth - CGFloat(CellWidth + SpacingWidth)) / 2
    let rightInset = leftInset

    return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}

don't forget to implement following protocol

UICollectionViewDelegateFlowLayout

Solution 2:[2]

flowLayout.minimumLineSpacing = 0

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 VishalPethani
Solution 2 Petro Nepyivoda