UICollectionView设置列数
我刚开始学习UICollectionViews。 我想知道如果有人知道如何指定一个collectionview中的列数。 默认设置为3(iPhone /人像)。 我已经看了文档,似乎无法find一个简洁的答案。
CollectionViewsfunction非常强大,而且价格昂贵。 很多,和很多的select。 正如omz所说:
有多种方法可以更改列数
我build议实现<UICollectionViewDelegateFlowLayout>
协议,让您访问以下方法,您可以更好地控制您的UICollectionView
的布局,而不需要子类化:
-
collectionView:layout:insetForSectionAtIndex:
-
collectionView:layout:minimumInteritemSpacingForSectionAtIndex:
-
collectionView:layout:minimumLineSpacingForSectionAtIndex:
-
collectionView:layout:referenceSizeForFooterInSection:
-
collectionView:layout:referenceSizeForHeaderInSection:
-
collectionView:layout:sizeForItemAtIndexPath:
另外,实现下面的方法将迫使你的UICollectionView更新它的方向变化的布局:(比如你想重新调整单元格的大小,使它们伸展)
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{ [self.myCollectionView.collectionViewLayout invalidateLayout]; }
另外,这里有2个关于UICollectionViews
非常好的教程:
http://www.raywenderlich.com/22324/beginning-uicollectionview-in-ios-6-part-12
我在我的UICollectionViewDelegateFlowLayout
上实现了UICollectionViewDelegateFlowLayout
,并覆盖了负责确定Cell大小的方法。 然后我把屏幕宽度和我的列要求划分。 例如,我想在每个屏幕大小上有3列。 所以这里是我的代码看起来像 –
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { CGRect screenRect = [[UIScreen mainScreen] bounds]; CGFloat screenWidth = screenRect.size.width; float cellWidth = screenWidth / 3.0; //Replace the divisor with the column count requirement. Make sure to have it in float. CGSize size = CGSizeMake(cellWidth, cellWidth); return size; }
使用Swift 3,您可以使用以下三个实现中的一个来设置UICollectionView
每行的项目数量。
#1。 使用UICollectionViewFlowLayout
itemSize
属性和UICollectionViewLayout
invalidationContext(forBoundsChange:)
方法
ColumnFlowLayout.swift:
import UIKit class ColumnFlowLayout: UICollectionViewFlowLayout { let cellsPerRow: Int override var itemSize: CGSize { get { guard let collectionView = collectionView else { return super.itemSize } let marginsAndInsets = sectionInset.left + sectionInset.right + minimumInteritemSpacing * CGFloat(cellsPerRow - 1) let itemWidth = ((collectionView.bounds.size.width - marginsAndInsets) / CGFloat(cellsPerRow)).rounded(.down) return CGSize(width: itemWidth, height: itemWidth) } set { super.itemSize = newValue } } init(cellsPerRow: Int, minimumInteritemSpacing: CGFloat = 0, minimumLineSpacing: CGFloat = 0, sectionInset: UIEdgeInsets = .zero) { self.cellsPerRow = cellsPerRow super.init() self.minimumInteritemSpacing = minimumInteritemSpacing self.minimumLineSpacing = minimumLineSpacing self.sectionInset = sectionInset } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func invalidationContext(forBoundsChange newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext { let context = super.invalidationContext(forBoundsChange: newBounds) as! UICollectionViewFlowLayoutInvalidationContext context.invalidateFlowLayoutDelegateMetrics = newBounds != collectionView?.bounds return context } }
CollectionViewController.swift:
import UIKit class CollectionViewController: UICollectionViewController { let columnLayout = ColumnFlowLayout( cellsPerRow: 5, minimumInteritemSpacing: 10, minimumLineSpacing: 10, sectionInset: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) ) override func viewDidLoad() { super.viewDidLoad() collectionView?.collectionViewLayout = columnLayout } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 29 } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { return collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) } }
#2。 使用UICollectionViewDelegateFlowLayout
collectionView(_:layout:sizeForItemAt:)
和UIContentContainer
协议viewWillTransition(to:with:)
方法
import UIKit class CollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { let margin: CGFloat = 10 let cellsPerRow = 5 override func viewDidLoad() { super.viewDidLoad() guard let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout else { return } flowLayout.minimumInteritemSpacing = margin flowLayout.minimumLineSpacing = margin flowLayout.sectionInset = UIEdgeInsets(top: margin, left: margin, bottom: margin, right: margin) } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 29 } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { return collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let flowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout let marginsAndInsets = flowLayout.sectionInset.left + flowLayout.sectionInset.right + flowLayout.minimumInteritemSpacing * CGFloat(cellsPerRow - 1) let itemWidth = ((collectionView.bounds.size.width - marginsAndInsets) / CGFloat(cellsPerRow)).rounded(.down) return CGSize(width: itemWidth, height: itemWidth) } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { collectionView?.collectionViewLayout.invalidateLayout() super.viewWillTransition(to: size, with: coordinator) } }
#3。 使用UICollectionViewDelegateFlowLayout
collectionView(_:layout:sizeForItemAt:)
和UICollectionViewFlowLayout
estimatedItemSize
属性
请注意,这段代码只适用于Springs和Struts。
import UIKit class CollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { let margin: CGFloat = 10 let cellsPerRow = 5 override func viewDidLoad() { super.viewDidLoad() guard let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout else { return } flowLayout.minimumInteritemSpacing = margin flowLayout.minimumLineSpacing = margin flowLayout.sectionInset = UIEdgeInsets(top: margin, left: margin, bottom: margin, right: margin) flowLayout.estimatedItemSize = flowLayout.itemSize // CGSize(width: 50, height: 50) } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 29 } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { return collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let flowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout let marginsAndInsets = flowLayout.sectionInset.left + flowLayout.sectionInset.right + flowLayout.minimumInteritemSpacing * CGFloat(cellsPerRow - 1) let itemWidth = ((collectionView.bounds.size.width - marginsAndInsets) / CGFloat(cellsPerRow)).rounded(.down) return CGSize(width: itemWidth, height: itemWidth) } }
你可以在这个Github仓库中find这些例子和捆绑在Xcode项目中的另一个例子: CollectionView-Columns-Examples 。
扩大noob的答案:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout let totalSpace = flowLayout.sectionInset.left + flowLayout.sectionInset.right + (flowLayout.minimumInteritemSpacing * CGFloat(numberOfItemsPerRow - 1)) let size = Int((collectionView.bounds.width - totalSpace) / CGFloat(numberOfItemsPerRow)) return CGSize(width: size, height: size) }
这允许单元之间的任何间隔。 它假设一个名为numberOfItemsPerRow
的Int
成员variables,并且所有单元格都是正方形且大小相同。 正如在jhilgert00的答案中指出的,我们还必须对方向更改做出反应,但是现在通过使用viewWillTransitionToSize
因为willRotateToInterfaceOrientation
已折旧。
这里是Swift 3的工作代码,有两列布局:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let nbCol = 2 let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout let totalSpace = flowLayout.sectionInset.left + flowLayout.sectionInset.right + (flowLayout.minimumInteritemSpacing * CGFloat(nbCol - 1)) let size = Int((collectionView.bounds.width - totalSpace) / CGFloat(nbCol)) return CGSize(width: size, height: size) }
随意将“nbCol”更改为所需的列数。
更新到Swift 3:
而不是stream布局,我更喜欢使用自定义布局的特定列号和行号。 因为:
- 如果列号很大,可以水平拖动。
- 由于使用列和行,因此在逻辑上更为可接受。
正常单元格和标题单元格:(将UILabel作为IBOutlet添加到您的xib):
class CollectionViewCell: UICollectionViewCell { @IBOutlet weak var label: UILabel! override func awakeFromNib() { super.awakeFromNib() // Initialization code self.backgroundColor = UIColor.black label.textColor = UIColor.white } } class CollectionViewHeadCell: UICollectionViewCell { @IBOutlet weak var label: UILabel! override func awakeFromNib() { super.awakeFromNib() // Initialization code self.backgroundColor = UIColor.darkGray label.textColor = UIColor.white } }
自定义布局:
let cellHeight: CGFloat = 100 let cellWidth: CGFloat = 100 class CustomCollectionViewLayout: UICollectionViewLayout { private var numberOfColumns: Int! private var numberOfRows: Int! // It is two dimension array of itemAttributes private var itemAttributes = [[UICollectionViewLayoutAttributes]]() // It is one dimension of itemAttributes private var cache = [UICollectionViewLayoutAttributes]() override func prepare() { if self.cache.isEmpty { self.numberOfColumns = self.collectionView?.numberOfItems(inSection: 0) self.numberOfRows = self.collectionView?.numberOfSections // Dynamically change cellWidth if total cell width is smaller than whole bounds /* if (self.collectionView?.bounds.size.width)!/CGFloat(self.numberOfColumns) > cellWidth { self.cellWidth = (self.collectionView?.bounds.size.width)!/CGFloat(self.numberOfColumns) } */ for row in 0..<self.numberOfRows { var row_temp = [UICollectionViewLayoutAttributes]() for column in 0..<self.numberOfColumns { let indexPath = NSIndexPath(item: column, section: row) let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath as IndexPath) attributes.frame = CGRect(x: cellWidth*CGFloat(column), y: cellHeight*CGFloat(row), width: cellWidth, height: cellHeight) row_temp.append(attributes) self.cache.append(attributes) } self.itemAttributes.append(row_temp) } } } override var collectionViewContentSize: CGSize { return CGSize(width: CGFloat(self.numberOfColumns)*cellWidth, height: CGFloat(self.numberOfRows)*cellHeight) } override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var layoutAttributes = [UICollectionViewLayoutAttributes]() for attributes in cache { if attributes.frame.intersects(rect) { layoutAttributes.append(attributes) } } return layoutAttributes } }
的CollectionView:
let CellIdentifier = "CellIdentifier" let HeadCellIdentifier = "HeadCellIdentifier" class CollectionView: UICollectionView, UICollectionViewDelegate, UICollectionViewDataSource { init() { let layout = CustomCollectionViewLayout() super.init(frame: CGRect.zero, collectionViewLayout: layout) self.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: CellIdentifier) self.register(UINib(nibName: "CollectionViewHeadCell", bundle: nil), forCellWithReuseIdentifier: HeadCellIdentifier) self.isDirectionalLockEnabled = true self.dataSource = self self.delegate = self } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func updateCollectionView() { DispatchQueue.main.async { self.reloadData() } } // MARK: CollectionView datasource func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 20 } func numberOfSections(in collectionView: UICollectionView) -> Int { return 20 } override func numberOfItems(inSection section: Int) -> Int { return 20 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let column = (indexPath as NSIndexPath).row let row = (indexPath as NSIndexPath).section if column == 0 { let cell : CollectionViewHeadCell = collectionView.dequeueReusableCell(withReuseIdentifier: HeadCellIdentifier, for: indexPath) as! CollectionViewHeadCell cell.label.text = "\(row)" return cell } else if row == 0 { let cell : CollectionViewHeadCell = collectionView.dequeueReusableCell(withReuseIdentifier: HeadCellIdentifier, for: indexPath) as! CollectionViewHeadCell cell.label.text = "\(column)" return cell } else { let cell : CollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: CellIdentifier, for: indexPath) as! CollectionViewCell cell.label.text = String(format: "%d", arguments: [indexPath.section*indexPath.row]) return cell } } // MARK: CollectionView delegate func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let column = (indexPath as NSIndexPath).row let row = (indexPath as NSIndexPath).section print("\(column) \(row)") } }
使用ViewController中的CollectionView:
class ViewController: UIViewController { let collectionView = CollectionView() override func viewDidLoad() { collectionView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(collectionView) self.view.backgroundColor = UIColor.red self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[collectionView]|", options: [], metrics: nil, views: ["collectionView": collectionView])) self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[collectionView]|", options: [], metrics: nil, views: ["collectionView": collectionView])) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) collectionView.updateCollectionView() } }
最后你可以有花哨的CollectionView!
因为UICollectionView
非常灵活,您可以通过多种方式更改列的数量,具体取决于您使用的布局types。
UICollectionViewFlowLayout
(这可能是你正在使用的)不直接指定数量的列(因为它取决于视图的大小/方向)。 最简单的方法是设置itemSize
属性和/或minimumInteritemSpacing
/ minimumLineSpacing
。
如果你懒惰使用委托。
extension UICollectionView { func setItemsInRow(items: Int) { if let layout = self.collectionViewLayout as? UICollectionViewFlowLayout { let contentInset = self.contentInset let itemsInRow: CGFloat = CGFloat(items); let innerSpace = layout.minimumInteritemSpacing * (itemsInRow - 1.0) let insetSpace = contentInset.left + contentInset.right + layout.sectionInset.left + layout.sectionInset.right let width = floor((CGRectGetWidth(frame) - insetSpace - innerSpace) / itemsInRow); layout.itemSize = CGSizeMake(width, width) } } }
PS:也应该在循环之后调用
Swift 3.0。 适用于水平和垂直滚动方向和可变间距
指定列数
let numberOfColumns: CGFloat = 3
configurationflowLayout
来呈现指定的numberOfColumns
if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout { let horizontalSpacing = flowLayout.scrollDirection == .vertical ? flowLayout.minimumInteritemSpacing : flowLayout.minimumLineSpacing let cellWidth = (view.frame.width - max(0, numberOfColumns - 1)*horizontalSpacing)/numberOfColumns flowLayout.itemSize = CGSize(width: cellWidth, height: cellWidth) }
它的所有关于您想要绘制的布局。 您可以创build从UICollectionViewFlowLayoutinheritance的自定义类。 目前没有任何直接设置列的方法。 如果你想实现这种function,你需要手动完成。 您需要在自定义stream布局类中处理它。
现在问题会出现,你会怎么做? 如果你不想打扰细胞框架,你可以调整
collectionView:layout:minimumInteritemSpacingForSectionAtIndex: collectionView:layout:minimumLineSpacingForSectionAtIndex:
另一种方法是提供你自己的细胞位置。 通过覆盖以下两种方法,这将在您的布局形成期间被调用。
- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path
UICollectionViewLayoutAttributes是处理单元位置,框架,Zindex等的类
完美的解决scheme是使用UICollectionViewDelegateFlowLayout,但你可以很容易地计算单元格的宽度,并根据你想要的列数
棘手的是使没有分数的宽度
(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { CGFloat screenWidth = self.view.frame.size.width; CGFloat marginWidth = (screenWidth - collectionView.frame.size.width); CGFloat cellWith = (collectionView.frame.size.width - marginWidth )/3; cellWith= floorf(cellWith); CGSize retval = CGSizeMake(cellWith,cellWith); return retval;}
我只是想追加Imanou Petit的答案#2。 为了确保边距精确而不考虑屏幕宽度,我使用具有所需边距的迭代解算器,并将列数作为input。 我还添加了一个方向性的标志,将他们的最终利润与他们的目标进行比较。
迭代求解器如下所示,并返回cellWidth和margin。
private func iterativeCellSpacing(targetMargins : CGFloat, cellsPerRow : Int, isMinTarget : Bool) -> (CGFloat, CGFloat) { var w : CGFloat = 0 var m : CGFloat = targetMargins let cols : CGFloat = CGFloat(cellsPerRow) let numMargins : CGFloat = cols + 1.0 let screenWidth : CGFloat = collectionView!.bounds.size.width var delta = CGFloat.greatestFiniteMagnitude while abs(delta) > 0.001 { let totalMarginSpacing = numMargins * m let totalCellSpacing = screenWidth - totalMarginSpacing if (isMinTarget) { w = floor(totalCellSpacing / cols) m = ceil((screenWidth - cols * w) / numMargins) } else { w = ceil(totalCellSpacing / cols) m = floor((screenWidth - cols * w) / numMargins) } delta = screenWidth - w * CGFloat(cellsPerRow) - m * numMargins } return (w, m) }
我这样称呼它:
fileprivate var margin: CGFloat = 20 fileprivate var cellWidth : CGFloat = 80 fileprivate let cellsPerRow = 4 override func viewDidLoad() { super.viewDidLoad() (cellWidth, margin) = iterativeCellSpacing(targetMargins: margin, cellsPerRow: 4, isMinTarget: true) ... }
然后,我将cellWidth和margin值应用到stream布局,如下所示:
extension MyCollectionController : UICollectionViewDelegateFlowLayout
{func collectionView(_ collectionView:UICollectionView,layout collectionViewViewLayout:UICollectionViewLayout,sizeForItemAt indexPath:IndexPath) – > CGSize {return CGSize(width:cellWidth,height:cellWidth)}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { collectionView?.collectionViewLayout.invalidateLayout() super.viewWillTransition(to: size, with: coordinator) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsetsMake(margin, margin, margin, margin) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return margin } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return margin }
}
希望这可以帮助。 可能有更简单的方法来确保利润率是准确的,但这是一种方法。 而且,这个代码还没有经过testing,允许旋转collectionviews的设备。
谢谢,
我做了一个收集布局。
要使分隔符可见,请将集合视图的背景颜色设置为灰色。 每节一行。
用途:
let layout = GridCollectionViewLayout() layout.cellHeight = 50 // if not set, cellHeight = Collection.height/numberOfSections layout.cellWidth = 50 // if not set, cellWidth = Collection.width/numberOfItems(inSection) collectionView.collectionViewLayout = layout
布局:
import UIKit class GridCollectionViewLayout: UICollectionViewLayout { var cellWidth : CGFloat = 0 var cellHeight : CGFloat = 0 var seperator: CGFloat = 1 private var cache = [UICollectionViewLayoutAttributes]() override func prepare() { guard let collectionView = self.collectionView else { return } self.cache.removeAll() let numberOfSections = collectionView.numberOfSections if cellHeight <= 0 { cellHeight = (collectionView.bounds.height - seperator*CGFloat(numberOfSections-1))/CGFloat(numberOfSections) } for section in 0..<collectionView.numberOfSections { let numberOfItems = collectionView.numberOfItems(inSection: section) let cellWidth2 : CGFloat if cellWidth <= 0 { cellWidth2 = (collectionView.bounds.width - seperator*CGFloat(numberOfItems-1))/CGFloat(numberOfItems) } else { cellWidth2 = cellWidth } for row in 0..<numberOfItems { let indexPath = NSIndexPath(row: row, section: section) let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath as IndexPath) attributes.frame = CGRect(x: (cellWidth2+seperator)*CGFloat(row), y: (cellHeight+seperator)*CGFloat(section), width: cellWidth2, height: cellHeight) //row_temp.append(attributes) self.cache.append(attributes) } //self.itemAttributes.append(row_temp) } } override var collectionViewContentSize: CGSize { guard let collectionView = collectionView else { return CGSize.zero } if (collectionView.numberOfSections <= 0) { return collectionView.bounds.size } let width:CGFloat if cellWidth <= 0 { width = collectionView.bounds.width } else { width = cellWidth*CGFloat(collectionView.numberOfItems(inSection: 0)) } let numberOfSections = CGFloat(collectionView.numberOfSections) var height:CGFloat = 0 height += numberOfSections * cellHeight height += (numberOfSections - 1) * seperator return CGSize(width: width, height: height) } override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var layoutAttributes = [UICollectionViewLayoutAttributes]() for attributes in cache { if attributes.frame.intersects(rect) { layoutAttributes.append(attributes) } } return layoutAttributes } override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { return cache[indexPath.item] } }
这个答案适用于swift 3.0 – >
首先符合协议:
UICollectionViewDelegateFlowLayout
然后添加这些方法:
//this method is for the size of items func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = collectionView.frame.width/3 let height : CGFloat = 160.0 return CGSize(width: width, height: height) } //these methods are to configure the spacing between items func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsetsMake(0,0,0,0) } 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 0 }