Answer for Objective-C
and Swift2.0
: How to center align the cells of a UICollectionView?
I usually would try to conver
This ended up being the solution I used. Read the code comments for a better understanding. Swift 5
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
//Where elements_count is the count of all your items in that
//Collection view...
let cellCount = CGFloat(elements_count)
//If the cell count is zero, there is no point in calculating anything.
if cellCount > 0 {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let cellWidth = flowLayout.itemSize.width + flowLayout.minimumInteritemSpacing
//20.00 was just extra spacing I wanted to add to my cell.
let totalCellWidth = cellWidth*cellCount + 20.00 * (cellCount-1)
let contentWidth = collectionView.frame.size.width - collectionView.contentInset.left - collectionView.contentInset.right
if (totalCellWidth < contentWidth) {
//If the number of cells that exists take up less room than the
//collection view width... then there is an actual point to centering them.
//Calculate the right amount of padding to center the cells.
let padding = (contentWidth - totalCellWidth) / 2.0
return UIEdgeInsets(top: 0, left: padding, bottom: 0, right: padding)
} else {
//Pretty much if the number of cells that exist take up
//more room than the actual collectionView width, there is no
// point in trying to center them. So we leave the default behavior.
return UIEdgeInsets(top: 0, left: 40, bottom: 0, right: 40)
}
}
return UIEdgeInsets.zero
}
Here's a recent solution, works for Swift 5.0
extension YourViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int) -> UIEdgeInsets {
let itemWidth = 80
let spacingWidth = 4
let numberOfItems = collectionView.numberOfItems(inSection: section)
let cellSpacingWidth = numberOfItem * spacingWidth
let totalCellWidth = numberOfItems * itemWidth + cellSpacingWidth
let inset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth)) / 2
return UIEdgeInsets(top: 5, left: inset, bottom: 5, right: inset)
}
}
Assuming that you are conforming to UICollectionViewDelegateFlowLayout, it should be:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let edgeInsets = (screenWight - (CGFloat(elements.count) * 50) - (CGFloat(elements.count) * 10)) / 2
return UIEdgeInsets(top: 0, left: edgeInsets, bottom: 0, right: 0)
}
The method that you are looking for is present with a different signature in Swift 3
. The new signature is this:
optional public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
P.S: This method is present in UICollectionViewDelegateFlowLayout
protocol.
Hope this would help.
I think the easiest solution in case your collectionView has one row is to substitute it by a stackView inside a scrollview so you can set the spacing you want between the views. Besides, if you want some padding you will be able apply it.
Slight adaptation of @rottenoats answer. This is more generic.
Most importantly remember to make your view controller conform to the UICollectionViewDelegateFlowLayout protocol.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
guard let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout else {
return .zero
}
let cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
if cellCount > 0 {
let cellWidth = flowLayout.itemSize.width + flowLayout.minimumInteritemSpacing
let totalCellWidth = cellWidth * cellCount
let contentWidth = collectionView.frame.size.width - collectionView.contentInset.left - collectionView.contentInset.right - flowLayout.headerReferenceSize.width - flowLayout.footerReferenceSize.width
if (totalCellWidth < contentWidth) {
let padding = (contentWidth - totalCellWidth + flowLayout.minimumInteritemSpacing) / 2.0
return UIEdgeInsetsMake(0, padding, 0, 0)
}
}
return .zero
}