ios 如何水平居中 UICollectionView 单元格?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34267662/
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 horizontally UICollectionView Cells?
提问by RaptoX
I have done some research, but I couldn't find any code example on how to center cells in a UICollectionView horizontally.
我做了一些研究,但我找不到任何关于如何在 UICollectionView 中水平居中单元格的代码示例。
instead of the first cell being like this X00, I want it to be like this 0X0. is there any way to accomplish this?
而不是第一个单元格像这样X00,我希望它像这样0X0。有没有办法做到这一点?
EDIT:
编辑:
to visualize what I want:
可视化我想要的:
I need it to look like version B when there is only one element in the CollectionView. When I got more than one element, then it should be like version A but with more elements.
当 CollectionView 中只有一个元素时,我需要它看起来像版本 B。当我得到多个元素时,它应该像版本 A 一样,但具有更多元素。
At the moment it looks like Version A when I have only 1 element, and I wonder how I can make it look like B.
目前,当我只有 1 个元素时,它看起来像版本 A,我想知道如何使它看起来像 B。
Thanks for the help!
谢谢您的帮助!
回答by Darshan Patel.
Its not a good idea to use a library, if your purpose is only this i.e to centre align.
如果您的目的只是为了居中对齐,则使用库不是一个好主意。
Better you can do this simple calculation in your collectionViewLayout function.
更好的是,您可以在 collectionViewLayout 函数中进行这个简单的计算。
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
let totalCellWidth = CellWidth * CellCount
let totalSpacingWidth = CellSpacing * (CellCount - 1)
let leftInset = (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
let rightInset = leftInset
return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}
回答by Ahmed Safadi
Swift 5.1
斯威夫特 5.1
func centerItemsInCollectionView(cellWidth: Double, numberOfItems: Double, spaceBetweenCell: Double, collectionView: UICollectionView) -> UIEdgeInsets {
let totalWidth = cellWidth * numberOfItems
let totalSpacingWidth = spaceBetweenCell * (numberOfItems - 1)
let leftInset = (collectionView.frame.width - CGFloat(totalWidth + totalSpacingWidth)) / 2
let rightInset = leftInset
return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}
Swift 4.2
斯威夫特 4.2
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let totalCellWidth = 80 * collectionView.numberOfItems(inSection: 0)
let totalSpacingWidth = 10 * (collectionView.numberOfItems(inSection: 0) - 1)
let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
let rightInset = leftInset
return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}
Swift 3
斯威夫特 3
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
let totalCellWidth = 80 * collectionView.numberOfItems(inSection: 0)
let totalSpacingWidth = 10 * (collectionView.numberOfItems(inSection: 0) - 1)
let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
let rightInset = leftInset
return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}
don't forget to add the protocol
不要忘记添加协议
UICollectionViewDelegateFlowLayout
回答by oscar castellon
Try this for Swift 4
试试这个 Swift 4
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let cellWidth : CGFloat = 165.0
let numberOfCells = floor(self.view.frame.size.width / cellWidth)
let edgeInsets = (self.view.frame.size.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)
return UIEdgeInsetsMake(15, edgeInsets, 0, edgeInsets)
}
Add your cellWidth instead 165.0
添加您的 cellWidth 而不是 165.0
回答by TwoStraws
I use KTCenterFlowLayoutfor this, and it works great. It's a custom subclass of UICollectionViewFlowLayoutthat centres cells as you want. (Note: this isn't a trivial thing to solve by posting some code, which is why I'm linking to a GitHub project!)
我为此使用了KTCenterFlowLayout,而且效果很好。它是根据需要UICollectionViewFlowLayout将单元格居中的自定义子类。(注意:这不是通过发布一些代码来解决的微不足道的事情,这就是我链接到 GitHub 项目的原因!)
回答by Stunner
An objective-C version of Darshan Patel's answer:
Darshan Patel 答案的客观 C 版本:
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
CGFloat totalCellWidth = kItemWidth * self.dataArray.count;
CGFloat totalSpacingWidth = kSpacing * (((float)self.dataArray.count - 1) < 0 ? 0 :self.dataArray.count - 1);
CGFloat leftInset = (self.bounds.size.width - (totalCellWidth + totalSpacingWidth)) / 2;
CGFloat rightInset = leftInset;
UIEdgeInsets sectionInset = UIEdgeInsetsMake(0, leftInset, 0, rightInset);
return sectionInset;
}
回答by MXV
Slightly modifying @Safad Funy's answer, this is what worked for me in the lattest version of Swift & iOS. In this case I wanted the cells's width to be a third of the size of the collection view.
稍微修改@Safad Funy 的答案,这在最新版本的 Swift 和 iOS 中对我有用。在这种情况下,我希望单元格的宽度是集合视图大小的三分之一。
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let totalCellWidth = Int(collectionView.layer.frame.size.width) / 3 * collectionView.numberOfItems(inSection: 0)
let totalSpacingWidth = (collectionView.numberOfItems(inSection: 0) - 1)
let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
let rightInset = leftInset
return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}
回答by S. Matsepura
You can use this extension (Swift 4).
您可以使用此扩展程序 (Swift 4)。
It can center cells with if you collectionViewhave layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize.
如果您collectionView有layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize.
It work with any cells size and work perfectly when scrollDirection = .horizontal
它适用于任何细胞大小,并且在以下情况下完美运行 scrollDirection = .horizontal
public extension UICollectionView {
func centerContentHorizontalyByInsetIfNeeded(minimumInset: UIEdgeInsets) {
guard let layout = collectionViewLayout as? UICollectionViewFlowLayout,
layout.scrollDirection == .horizontal else {
assertionFailure("\(#function): layout.scrollDirection != .horizontal")
return
}
if layout.collectionViewContentSize.width > frame.size.width {
contentInset = minimumInset
} else {
contentInset = UIEdgeInsets(top: minimumInset.top,
left: (frame.size.width - layout.collectionViewContentSize.width) / 2,
bottom: minimumInset.bottom,
right: 0)
}
}
}
final class Foo: UIViewController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.centerContentHorizontalyByInsetIfNeeded(minimumInset: yourDefaultInset)
}
}
Hope it's help you!
希望对你有帮助!
回答by Saeed Ir
Here is the newer version for Swift 5which also works fine when the cells are more than one row:
这是Swift 5的较新版本,当单元格多于一行时,它也能正常工作:
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
var cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
var collectionWidth = collectionView.frame.size.width
var totalWidth: CGFloat
if #available(iOS 11.0, *) {
collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
}
repeat {
totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
cellCount -= 1
} while totalWidth >= collectionWidth
if (totalWidth > 0) {
let edgeInset = (collectionWidth - totalWidth) / 2
return UIEdgeInsets.init(top: flowLayout.sectionInset.top, left: edgeInset, bottom: flowLayout.sectionInset.bottom, right: edgeInset)
} else {
return flowLayout.sectionInset
}
}
Please make sure your class conformsto UICollectionViewDelegateFlowLayoutprotocol.
请确保你的类符合到UICollectionViewDelegateFlowLayout协议。
回答by EVGENIY DANILOV
Swift 4.2(Horizontally and Vertically). It's small upgrade of Pink Panther code and big thanks him!
Swift 4.2(水平和垂直)。这是粉红豹代码的小升级,非常感谢他!
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let cellWidth: CGFloat = flowLayout.itemSize.width
let cellHieght: CGFloat = flowLayout.itemSize.height
let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
let cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
var collectionWidth = collectionView.frame.size.width
var collectionHeight = collectionView.frame.size.height
if #available(iOS 11.0, *) {
collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
collectionHeight -= collectionView.safeAreaInsets.top + collectionView.safeAreaInsets.bottom
}
let totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
let totalHieght = cellHieght * cellCount + cellSpacing * (cellCount - 1)
if totalWidth <= collectionWidth {
let edgeInsetWidth = (collectionWidth - totalWidth) / 2
print(edgeInsetWidth, edgeInsetWidth)
return UIEdgeInsets(top: 5, left: edgeInsetWidth, bottom: flowLayout.sectionInset.top, right: edgeInsetWidth)
} else {
let edgeInsetHieght = (collectionHeight - totalHieght) / 2
print(edgeInsetHieght, edgeInsetHieght)
return UIEdgeInsets(top: edgeInsetHieght, left: flowLayout.sectionInset.top, bottom: edgeInsetHieght, right: flowLayout.sectionInset.top)
}
}
Make sure your class conforms to UICollectionViewDelegateFlowLayoutprotocol
确保您的类符合UICollectionViewDelegateFlowLayout协议
回答by Haroldo Gondim
Swift 4
斯威夫特 4
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let cellWidth: CGFloat = 170.0 // Your cell width
let numberOfCells = floor(view.frame.size.width / cellWidth)
let edgeInsets = (view.frame.size.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)
return UIEdgeInsetsMake(0, edgeInsets, 0, edgeInsets)
}
}


