How to center align the cells of a UICollectionView in Swift3.0?

kemicofa ghost picture kemicofa ghost · Nov 14, 2016 · Viewed 26.9k times · Source

Description:

Answer for Objective-C and Swift2.0: How to center align the cells of a UICollectionView?

I usually would try to convert the Swift2.0 answer to the Swift3.0 solution, however the method:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
        let edgeInsets = (screenWight - (CGFloat(elements.count) * 50) - (CGFloat(elements.count) * 10)) / 2
        return UIEdgeInsetsMake(0, edgeInsets, 0, 0);
    }

doesn't seem to exist in Swift3.0,and the only other method I found that seems useful is:

func collectionView(_ collectionView: UICollectionView, transitionLayoutForOldLayout fromLayout: UICollectionViewLayout, newLayout toLayout: UICollectionViewLayout) -> UICollectionViewTransitionLayout {
        <#code#>
}

but I am unsure how to implement it correctly.

Question:

How to center align the cells of a UICollectionView in Swift3.0?

(A simple and general solution for iOS and tvOS would be perfect)

Answer

jbouaziz picture jbouaziz · Jun 12, 2017

While rottenoats answer is great, it has an extra spacing bug and doesn't use much of the available swift 3 syntax. I've fixed that and reduced the number of dependencies to local variables.

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

    // Make sure that the number of items is worth the computing effort.
    guard let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout,
        let dataSourceCount = collectionView.dataSource?.collectionView(collectionView, numberOfItemsInSection: section),
        dataSourceCount > 0 else {
            return .zero
    }


    let cellCount = CGFloat(dataSourceCount)
    let itemSpacing = flowLayout.minimumInteritemSpacing
    let cellWidth = flowLayout.itemSize.width + itemSpacing
    var insets = flowLayout.sectionInset


    // Make sure to remove the last item spacing or it will
    // miscalculate the actual total width.
    let totalCellWidth = (cellWidth * cellCount) - itemSpacing
    let contentWidth = collectionView.frame.size.width - collectionView.contentInset.left - collectionView.contentInset.right


    // If the number of cells that exist take up less room than the
    // collection view width, then center the content with the appropriate insets.
    // Otherwise return the default layout inset.
    guard totalCellWidth < contentWidth else {
        return insets
    }


    // Calculate the right amount of padding to center the cells.
    let padding = (contentWidth - totalCellWidth) / 2.0
    insets.left = padding
    insets.right = padding
    return insets
}

N.B.: This snippet only works for an horizontal scrolling but can easily be adjusted.