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 UICollectionViewFlowLayout
that 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 collectionView
have 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 UICollectionViewDelegateFlowLayout
protocol.
请确保你的类符合到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)
}
}