ios 如何在 Swift3.0 中居中对齐 UICollectionView 的单元格?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40585822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to center align the cells of a UICollectionView in Swift3.0?
提问by kemicofa ghost
Description:
描述:
Answer for Objective-C
and Swift2.0
: How to center align the cells of a UICollectionView?
回答Objective-C
和Swift2.0
:如何将 UICollectionView 的单元格居中对齐?
I usually would try to convert the Swift2.0
answer to the Swift3.0
solution, however the method:
我通常会尝试将Swift2.0
答案转换为Swift3.0
解决方案,但是方法:
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:
中似乎不存在Swift3.0
,我发现似乎有用的唯一其他方法是:
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 UICollectionView
in的单元格居中对齐Swift3.0
?
(A simple and general solution for iOS and tvOS would be perfect)
(适用于 iOS 和 tvOS 的简单通用的解决方案将是完美的)
回答by kemicofa ghost
This ended up being the solution I used. Read the code comments for a better understanding. Swift 5
这最终成为我使用的解决方案。阅读代码注释以获得更好的理解。斯威夫特 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
}
回答by jbouaziz
While rottenoatsanswer 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.
虽然rottenoats 的回答很好,但它有一个额外的间距错误,并且没有使用很多可用的 swift 3 语法。我已经解决了这个问题并减少了对局部变量的依赖。
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.
注意:此代码段仅适用于水平滚动,但可以轻松调整。
回答by mm282
Slight adaptation of @rottenoats answer. This is more generic.
对@rottenoats 的回答略有调整。这是更通用的。
Most importantly remember to make your view controller conform to the UICollectionViewDelegateFlowLayout protocol.
最重要的是记住让你的视图控制器符合 UICollectionViewDelegateFlowLayout 协议。
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
}
回答by Adeel
The method that you are looking for is present with a different signature in Swift 3
. The new signature is this:
您正在寻找的方法在Swift 3
. 新签名是这样的:
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.
PS:此方法存在于UICollectionViewDelegateFlowLayout
协议中。
希望这会有所帮助。
回答by Ahmad F
Assuming that you are conforming to UICollectionViewDelegateFlowLayout, it should be:
假设您符合UICollectionViewDelegateFlowLayout,它应该是:
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)
}
回答by Alexander Nikolenko
Here's a recent solution, works for Swift 5.0
这是最近的解决方案,适用于 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)
}
}
回答by yogesh wadhwa
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
let allCellWidth = KcellWidth * numberOfCell
let cellSpacingWidth = CellSpacing * (numberOfCell - 1)
let leftInset = (collectionViewWidth - CGFloat(allCellWidth + cellSpacingWidth)) / 2
let rightInset = leftInset
return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}
回答by Mehdi
You need to conformto UICollectionViewDelegateFlowLayout
protocol to find the collectionView(_:layout:insetForSectionAt:)
method, it is defined there. the following implementation works fine in swift 4 for a horizontal collectionView
您需要符合以UICollectionViewDelegateFlowLayout
协议找到collectionView(_:layout:insetForSectionAt:)
方法,它被定义在那里。以下实现在 swift 4 中适用于水平 collectionView
extension YourViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let cellWidth = CGFloat(integerLiteral: YourCellsWidth)
let count = self.YourCollectionViewDataSource.count
let top = CGFloat(integerLiteral: 0) // I don't need to set top and bottom spacing
let cellsAccumulatedWidth = CGFloat(integerLiteral: count) * cellWidth
let cellsSpacingAccumulatedWidth = CGFloat(integerLiteral: (count - 1) * 5)
let left = (self.collectionView.frame.size.width - cellsAccumulatedWidth - cellsSpacingAccumulatedWidth) / 2
let bottom = top
let right = left
return UIEdgeInsetsMake(top, left, bottom, right);
}
}
回答by Saeed Ir
This code should center horizontally any type of collection view even with extra items in Swift 4.0:
即使在Swift 4.0 中有额外的项目,此代码也应将任何类型的集合视图水平居中:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let cellWidth: CGFloat = flowLayout.itemSize.width
let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
let cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
var collectionWidth = collectionView.frame.size.width
if #available(iOS 11.0, *) {
collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
}
let totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
if totalWidth <= collectionWidth {
let edgeInset = (collectionWidth - totalWidth) / 2
return UIEdgeInsetsMake(flowLayout.sectionInset.top, edgeInset, flowLayout.sectionInset.bottom, edgeInset)
} else {
return flowLayout.sectionInset
}
}
Don't forget if you are not subclassing UICollectionViewController
, make sure your class conforms to UICollectionViewDelegateFlowLayout
protocol
不要忘记,如果您不是子类化UICollectionViewController
,请确保您的类符合UICollectionViewDelegateFlowLayout
协议
回答by nitin.agam
Use this solution for horizontal scrolling with the center align.
使用此解决方案进行居中对齐的水平滚动。
let totalCellWidth = Int(collectionView.frame.height * CGFloat(numberOfItems()))
// if total width is greater than collection's width, then no need to align center
if totalCellWidth > Int(collectionView.frame.width) {
return UIEdgeInsets.zero
}
let totalSpacingWidth = cellSpacing * (numberOfItems() - 1)
let leftInset = (collectionView.frame.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
let rightInset = leftInset
return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)