如何设置单元格间距和 UICollectionView-UICollectionViewFlowLayout 大小比率?

我试图添加 UICollectionViewViewController,我需要有3个单元格’每行’之间没有空格(它应该看起来像一个网格)。单元格的宽度应该是屏幕尺寸的三分之一,所以我认为 layout.item的宽度应该是相同的。但我得到了这个:

layout.itemSize width = screenSize.width/3

如果我减小这个大小(比如 7或者 8像素) ,效果会更好,但是行中的第三个单元格不是完全可见的,而且我仍然有那个空格(顶部和底部,以及左边和右边)。

enter image description here

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
var collectionView: UICollectionView?
var screenSize: CGRect!
var screenWidth: CGFloat!
var screenHeight: CGFloat!


override func viewDidLoad() {
super.viewDidLoad()


screenSize = UIScreen.mainScreen().bounds
screenWidth = screenSize.width
screenHeight = screenSize.height


// Do any additional setup after loading the view, typically from a nib
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
layout.itemSize = CGSize(width: screenWidth / 3, height: screenWidth / 3)
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionView!.dataSource = self
collectionView!.delegate = self
collectionView!.registerClass(CollectionViewCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
collectionView!.backgroundColor = UIColor.greenColor()
self.view.addSubview(collectionView!)
}


func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}


func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 20
}


func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as CollectionViewCell
cell.backgroundColor = UIColor.whiteColor()
cell.layer.borderColor = UIColor.blackColor().CGColor
cell.layer.borderWidth = 0.5
cell.frame.size.width = screenWidth / 3
cell.frame.size.height = screenWidth / 3


cell.textLabel?.text = "\(indexPath.section):\(indexPath.row)"
return cell
}
}
222383 次浏览

加上这两行

layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0

所以你有:

   // Do any additional setup after loading the view, typically from a nib.
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
layout.itemSize = CGSize(width: screenWidth/3, height: screenWidth/3)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
collectionView!.collectionViewLayout = layout

这将删除所有的空格,并给你一个网格布局:

enter image description here

如果希望第一列的宽度等于屏幕宽度,请添加以下函数:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if indexPath.row == 0
{
return CGSize(width: screenWidth, height: screenWidth/3)
}
return CGSize(width: screenWidth/3, height: screenWidth/3);


}

网格布局现在看起来像(我还在第一个单元格中添加了一个蓝色背景) : enter image description here

对于 Swift 3和 XCode 8 ,这是有效的

{
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let width = UIScreen.main.bounds.width
layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
layout.itemSize = CGSize(width: width / 2, height: width / 2)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
collectionView!.collectionViewLayout = layout
}

将此代码放入 viewDidLoad ()函数中。

对于 Swift 3和 XCode 8, 这是有效的

viewDidLoad()
{
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
var width = UIScreen.main.bounds.width
layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
width = width - 10
layout.itemSize = CGSize(width: width / 2, height: width / 2)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
collectionView!.collectionViewLayout = layout
}

如果你正在寻找 Swift 3,按照下面的步骤来实现:

func viewDidLoad() {


//Define Layout here
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()


//Get device width
let width = UIScreen.main.bounds.width


//set section inset as per your requirement.
layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)


//set cell item size here
layout.itemSize = CGSize(width: width / 2, height: width / 2)


//set Minimum spacing between 2 items
layout.minimumInteritemSpacing = 0


//set minimum vertical line spacing here between two lines in collectionview
layout.minimumLineSpacing = 0


//apply defined layout to collectionview
collectionView!.collectionViewLayout = layout


}

这在 Xcode 8.0和 Swift 3中得到了验证。

在某些情况下,在 viewDidLoadViewWillAppear中设置 UICollectionViewFlowLayout可能不会影响 CollectionView。

viewDidAppear中设置 UICollectionViewFlowLayout可能会导致在运行时查看单元格大小的变化。

在 Swift 3中的另一个解决方案:

extension YourViewController : UICollectionViewDelegateFlowLayout{


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
}


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let collectionViewWidth = collectionView.bounds.width
return CGSize(width: collectionViewWidth/3, height: collectionViewWidth/3)
}


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 20
}
}
let layout = myCollectionView.collectionViewLayout as? UICollectionViewFlowLayout
layout?.minimumLineSpacing = 8

Swift 4

let collectionViewLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
collectionViewLayout?.sectionInset = UIEdgeInsetsMake(0, 20, 0, 40)
collectionViewLayout?.invalidateLayout()

对于 Swift 3 + 和 Xcode 9 + ,请尝试使用以下命令

extension ViewController: UICollectionViewDelegateFlowLayout {


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {


let collectionWidth = collectionView.bounds.width
return CGSize(width: collectionWidth/3, height: collectionWidth/3)


}


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0


}

Swift 5: 对于动态单元格宽度的单元格之间均匀分布的空间,您可以通过提供 最小单元宽度值来使用下面的代码片段来充分利用容器空间。

private func collectionViewLayout() -> UICollectionViewLayout {
    

let layout = UICollectionViewFlowLayout()
layout.sectionHeadersPinToVisibleBounds = true
// Important: if direction is horizontal use minimumItemSpacing instead.
layout.scrollDirection = .vertical
    

let itemHeight: CGFloat = 240
let minCellWidth :CGFloat = 130.0
let minItemSpacing: CGFloat = 10
let containerWidth: CGFloat = self.view.bounds.width
let maxCellCountPerRow: CGFloat =  floor((containerWidth - minItemSpacing) / (minCellWidth+minItemSpacing ))
    

let itemWidth: CGFloat = floor( ((containerWidth - (2 * minItemSpacing) - (maxCellCountPerRow-1) * minItemSpacing) / maxCellCountPerRow  ) )
// Calculate the remaining space after substracting calculating cellWidth (Divide by 2 because of left and right insets)
let inset = max(minItemSpacing, floor( (containerWidth - (maxCellCountPerRow*itemWidth) - (maxCellCountPerRow-1)*minItemSpacing) / 2 ) )


    

layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
layout.minimumInteritemSpacing = min(minItemSpacing,inset)
layout.minimumLineSpacing = minItemSpacing
layout.sectionInset = UIEdgeInsets(top: minItemSpacing, left: inset, bottom: minItemSpacing, right: inset)


    

return layout
}

迅捷4,迅捷5,最简单的方法!

不需要创建 UICollectionViewFlowLayout()实例,只需在您的类上实现 UICollectionViewDelegateFlowLayout

extension MyCollectionView: UICollectionViewDelegateFlowLayout {


// Distance Between Item Cells
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 20
}
    

// Cell Margin
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
}


}

我们在 XCode 中有一个选项,选择 CollectionView 并转到导航器并更改 < strong > “ Min Spaces”,而不是编写一行代码

enter image description here