Creating Decoration View as Custom Column in UIcollection View

Creating decoration view as custom column in UICollection View

Small trick we can use to get this.

Cell size should be one - fifth of ViewController. So we can get 5 Cells in one row. U can create numberOfItems what do u need.

Create and store seat number in Dictionary. So we can avoid reuse.

I have did sample for 48 number of seats.

Coding

var busSeatNumDict = [Int : String]()
var pathWayNumber = Int()
var seatNumer = Int()

override func viewDidLoad() {
super.viewDidLoad()
pathWayNumber = 2 // CENTER - PASSENGER CAN WALK
seatNumer = 1 // STARTING NUMBER
for i in 0...59
{
if i == pathWayNumber // If it s centre, values empty to dictionary
{
busSeatNumDict[i] = ""
pathWayNumber = pathWayNumber + 5 // Position empty - 2,7,12,17,22 ...... like that
}
else
{
busSeatNumDict[i] = String(seatNumer)
seatNumer = seatNumer + 1
}

}
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! RulesCollectionViewCell

cell.alpha = 0 // Initially alpha 0
let text = busSeatNumDict[indexPath.row]!

if text == "" || text == "2"
{
cell.alpha = 0
}
else
{
cell.alpha = 1
}
cell.backgroundColor = UIColor.clear

cell.layer.borderColor = UIColor(red: 83/255, green: 50/255, blue: 129/255, alpha: 1.0).cgColor
cell.layer.borderWidth = 1.0
cell.txtLbl.text = text
cell.txtLbl.textAlignment = .center
cell.txtLbl.textColor = UIColor.darkGray
cell.layer.cornerRadius = 5
return cell
}

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 60
}

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

return CGSize(width: (self.collectionView?.frame.width)! / 5, height: (self.collectionView?.frame.width)! / 5)
}

Output

Sample Image

How To Achieve the desired Design in uicollection view using decorator view

You could do it like this,

  • Create two different types of decoration view, one for vertical line which is at the center of the collection view and other being horizontal which appear below two cell
  • Vertical decoration view is created only once for the whole view, while horizontal decoration view is created for a pair of two which appears below each row. For the last row, dont create the decoration view.
  • subclass UICollectionViewFlowLayout, and override override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? and return appropriate decoration view.

Here is how the layout looks for me,

Sample Image

And here is the code used for that,

CollectionViewController,

class ViewController: UICollectionViewController {

let images = ["Apple", "Banana", "Grapes", "Mango", "Orange", "Strawberry"]

init() {
let collectionViewLayout = DecoratedFlowLayout()
collectionViewLayout.register(HorizontalLineDecorationView.self,
forDecorationViewOfKind: HorizontalLineDecorationView.decorationViewKind)
collectionViewLayout.register(VerticalLineDecorationView.self,
forDecorationViewOfKind: VerticalLineDecorationView.decorationViewKind)
super.init(collectionViewLayout: collectionViewLayout)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.white
collectionView?.register(CollectionViewCell.self,
forCellWithReuseIdentifier: CollectionViewCell.CellIdentifier)
}
}

extension ViewController: UICollectionViewDelegateFlowLayout {

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CollectionViewCell.CellIdentifier,
for: indexPath) as! CollectionViewCell
let name = images[indexPath.item]
cell.imageView.image = UIImage(named: "\(name).png")
cell.label.text = name
return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return .zero
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10 + DecoratedFlowLayout.horizontalLineWidth
}

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

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

let width = (collectionView.bounds.size.width - DecoratedFlowLayout.verticalLineWidth) * 0.5
return CGSize(width: width,
height: width + 20)
}
}

CollectionViewCell,

class CollectionViewCell: UICollectionViewCell {

static let CellIdentifier = "CollectionViewCellIdentifier"

var imageView: UIImageView!
var label: UILabel!

override init(frame: CGRect) {
super.init(frame: frame)
createViews()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func createViews() {
imageView = UIImageView(frame: .zero)
imageView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(imageView)

label = UILabel(frame: .zero)
label.font = UIFont.systemFont(ofSize: 20)
label.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(label)

NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: contentView.topAnchor),
imageView.leftAnchor.constraint(equalTo: contentView.leftAnchor),
imageView.rightAnchor.constraint(equalTo: contentView.rightAnchor),
label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
label.leftAnchor.constraint(equalTo: contentView.leftAnchor),
label.rightAnchor.constraint(equalTo: contentView.rightAnchor),
label.topAnchor.constraint(equalTo: imageView.bottomAnchor),
label.heightAnchor.constraint(equalToConstant: 20)
])
}
}

DecoratedFlowLayout,

class DecoratedFlowLayout: UICollectionViewFlowLayout {

static let verticalLineWidth: CGFloat = 20
static let horizontalLineWidth: CGFloat = 20

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
minimumLineSpacing = 40 // should be equal to or greater than horizontalLineWidth
}

override init() {
super.init()
minimumLineSpacing = 40
}

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

guard let attributes = super.layoutAttributesForElements(in: rect) else {
return nil
}

var attributesCopy: [UICollectionViewLayoutAttributes] = []

for attribute in attributes {

attributesCopy += [attribute]

let indexPath = attribute.indexPath

if collectionView!.numberOfItems(inSection: indexPath.section) == 0 {
continue
}

let firstCell = IndexPath(item: 0,
section: indexPath.section)
let lastCell = IndexPath(item: collectionView!.numberOfItems(inSection: indexPath.section) - 1,
section: indexPath.section)

if let attributeForFirstItem = layoutAttributesForItem(at: firstCell),
let attributeForLastItem = layoutAttributesForItem(at: lastCell) {

let verticalLineDecorationView = UICollectionViewLayoutAttributes(forDecorationViewOfKind: VerticalLineDecorationView.decorationViewKind,
with: IndexPath(item: 0, section: indexPath.section))

let firstFrame = attributeForFirstItem.frame
let lastFrame = attributeForLastItem.frame

let frame = CGRect(x: collectionView!.bounds.midX - DecoratedFlowLayout.verticalLineWidth * 0.5,
y: firstFrame.minY,
width: DecoratedFlowLayout.verticalLineWidth,
height: lastFrame.maxY - firstFrame.minY)
verticalLineDecorationView.frame = frame

attributesCopy += [verticalLineDecorationView]
}

let contains = attributesCopy.contains { layoutAttribute in
layoutAttribute.indexPath == indexPath
&& layoutAttribute.representedElementKind == HorizontalLineDecorationView.decorationViewKind
}

let numberOfItemsInSection = collectionView!.numberOfItems(inSection: indexPath.section)

if indexPath.item % 2 == 0 && !contains && indexPath.item < numberOfItemsInSection - 2 {

let horizontalAttribute = UICollectionViewLayoutAttributes(forDecorationViewOfKind: HorizontalLineDecorationView.decorationViewKind,
with: indexPath)

let frame = CGRect(x: attribute.frame.minX,
y: attribute.frame.maxY + (minimumLineSpacing - DecoratedFlowLayout.horizontalLineWidth) * 0.5,
width: collectionView!.bounds.width,
height: DecoratedFlowLayout.horizontalLineWidth)

horizontalAttribute.frame = frame

attributesCopy += [horizontalAttribute]
}
}
return attributesCopy
}

override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
}

And decoration views

class VerticalLineDecorationView: UICollectionReusableView {

static let decorationViewKind = "VerticalLineDecorationView"

let verticalInset: CGFloat = 40

let lineWidth: CGFloat = 4.0

let lineView = UIView()

override init(frame: CGRect) {
super.init(frame: frame)

lineView.backgroundColor = .black

addSubview(lineView)

lineView.translatesAutoresizingMaskIntoConstraints = false

NSLayoutConstraint.activate([
lineView.widthAnchor.constraint(equalToConstant: lineWidth),
lineView.topAnchor.constraint(equalTo: topAnchor, constant: verticalInset),
lineView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -verticalInset),
lineView.centerXAnchor.constraint(equalTo: centerXAnchor),
])
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

class HorizontalLineDecorationView: UICollectionReusableView {

let horizontalInset: CGFloat = 20

let lineWidth: CGFloat = 4.0

static let decorationViewKind = "HorizontalLineDecorationView"

let lineView = UIView()

override init(frame: CGRect) {
super.init(frame: frame)

lineView.backgroundColor = .black

addSubview(lineView)

lineView.translatesAutoresizingMaskIntoConstraints = false

NSLayoutConstraint.activate([
lineView.heightAnchor.constraint(equalToConstant: lineWidth),
lineView.leftAnchor.constraint(equalTo: leftAnchor, constant: horizontalInset),
lineView.rightAnchor.constraint(equalTo: rightAnchor, constant: -horizontalInset),
lineView.centerYAnchor.constraint(equalTo: centerYAnchor),
])
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

I hope you can make use of it and tweak values to suit your own need. Some of the calculations might make sense to change to some level. But, I hope you get the idea about how this could be achieved.

how to get the instance of the decoration view in the collection view?

Answer my own question!
Thanks for this article!

First, subclass UICollectionViewLayoutAttributes and add any property you want.

Second, in the function layoutAttributesForDecorationViewOfKind(elementKind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes!, set the property.

Third, in the UICollectionReusableView class, override the function applyLayoutAttributes: to get the custom UICollectionViewLayoutAttributes instance that contains your property.

Done!

How to set each UICollectionView section in an individual column

I have it tried in UICollectionViewController.

Click CollectionView and change to CustomLayout [UICollectionViewLayout]

Sample Image

UICollectionViewController

let values = [["a","b","c","d","e","f"], ["a","b","c"], ["a","b","c","d"], ["a","b","c","d","e","f"], ["a","b","c","d","e","f"],["a","b","c","d","e","f"], ["a","b","c"], ["a","b","c","d"], ["a","b","c","d","e","f"], ["a","b","c","d","e","f"]]

override func viewDidLoad() {
super.viewDidLoad()

let XIB = UINib.init(nibName: "RulesExrView", bundle: Bundle.main)
rulesCollexnVw.register(XIB, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerreuse")
}

override func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return values.count
}

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return values[section].count
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! RulesCollectionViewCell

let text = values[indexPath.section][indexPath.item]
cell.backgroundColor = UIColor.clear

cell.layer.borderColor = UIColor(red: 81/255, green: 57/255, blue: 141/255, alpha: 1.0).cgColor
cell.layer.borderWidth = 1.0
cell.txtLbl.text = text
cell.txtLbl.textAlignment = .center
cell.txtLbl.textColor = .white
cell.layer.cornerRadius = 5
return cell
}

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

print("\n\n Selected indPath ", indexPath)
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

print("Kinddd ", kind)

switch kind {

case UICollectionElementKindSectionHeader:

if let supplementaryView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerreuse", for: indexPath) as? RulesReusableView {
// Configure Supplementary View
supplementaryView.backgroundColor = UIColor.clear
supplementaryView.headLbl.text = "Section \(indexPath.section)".uppercased()
supplementaryView.headLbl.textColor = UIColor.white

return supplementaryView
}

fatalError("Unable to Dequeue Reusable Supplementary View")

default:

assert(false, "Unexpected element kind")
}
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if UIDevice.current.orientation.isLandscape {
print("Landscape")

rulesCollexnVw.reloadData()

} else {
print("Portrait")

rulesCollexnVw.reloadData()
}
}

UICollectionViewLayout [Not UICollectionViewFlowLayout]

class RulesLayout: UICollectionViewLayout {

let CELL_HEIGHT = 30.0
let CELL_WIDTH = 100.0

let horizontalSpacing = 5.0
let verticalSpaing = 5.0
let headerSpacing = 40.0

let STATUS_BAR = UIApplication.shared.statusBarFrame.height

var portrait_Ypos : Double = 0.0

var cellAttrsDictionary = Dictionary<IndexPath, UICollectionViewLayoutAttributes>()
var contentSize = CGSize.zero

var dataSourceDidUpdate = true

override var collectionViewContentSize : CGSize {
return self.contentSize
}

override func prepare() {

dataSourceDidUpdate = false

if UIDevice.current.orientation == .landscapeLeft || UIDevice.current.orientation == .landscapeRight
{
if let sectionCount = collectionView?.numberOfSections, sectionCount > 0 {
for section in 0...sectionCount-1 {

let xPos = (Double(section) * CELL_WIDTH) + (Double(section) * horizontalSpacing)
var yPos : Double = 0.0
if let rowCount = collectionView?.numberOfItems(inSection: section), rowCount > 0 {
for item in 0...rowCount-1 {

let cellIndex = IndexPath(item: item, section: section)

if item == 0
{
portrait_Ypos = headerSpacing
}
else
{
portrait_Ypos = portrait_Ypos + CELL_HEIGHT + verticalSpaing
}

yPos = portrait_Ypos

let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex)
cellAttributes.frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)

// Determine zIndex based on cell type.
if section == 0 && item == 0 {
cellAttributes.zIndex = 4
} else if section == 0 {
cellAttributes.zIndex = 3
} else if item == 0 {
cellAttributes.zIndex = 2
} else {
cellAttributes.zIndex = 1
}
cellAttrsDictionary[cellIndex] = cellAttributes

}

}

}
}

let contentWidth = Double(collectionView!.numberOfSections) * CELL_WIDTH + (Double(collectionView!.numberOfSections - 1) * horizontalSpacing)
let contentHeight = Double(collectionView!.numberOfSections) * CELL_HEIGHT
self.contentSize = CGSize(width: contentWidth, height: contentHeight)

print("self.contentSizeself.contentSize ", self.contentSize)
}
else
{
if let sectionCount = collectionView?.numberOfSections, sectionCount > 0 {

for section in 0...sectionCount-1 {

let xPos = (Double(UIScreen.main.bounds.width) - CELL_WIDTH) / 2.0

if let rowCount = collectionView?.numberOfItems(inSection: section), rowCount > 0 {
for item in 0...rowCount-1 {

let cellIndex = IndexPath(item: item, section: section)
if section != 0
{
if item == 0
{
portrait_Ypos = portrait_Ypos + CELL_HEIGHT + headerSpacing
}
else
{

portrait_Ypos = portrait_Ypos + CELL_HEIGHT + verticalSpaing
}
}
else
{
if item == 0
{
portrait_Ypos = headerSpacing
}
else
{
portrait_Ypos = portrait_Ypos + CELL_HEIGHT + verticalSpaing
}
}

let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex)
cellAttributes.frame = CGRect(x: xPos, y: portrait_Ypos, width: CELL_WIDTH, height: CELL_HEIGHT)

if section == 0 && item == 0 {
cellAttributes.zIndex = 4
} else if section == 0 {
cellAttributes.zIndex = 3
} else if item == 0 {
cellAttributes.zIndex = 2
} else {
cellAttributes.zIndex = 1
}
cellAttrsDictionary[cellIndex] = cellAttributes

}

}

}
}

let contentWidth = UIScreen.main.bounds.width
let contentHeight = CGFloat(portrait_Ypos) + CGFloat(CELL_HEIGHT)
self.contentSize = CGSize(width: contentWidth, height: contentHeight)

print("sPort.contentSize ", self.contentSize)
}

}

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

var attributesInRect = [UICollectionViewLayoutAttributes]()

for cellAttributes in cellAttrsDictionary.values {
if rect.intersects(cellAttributes.frame) {

attributesInRect.append(cellAttributes)

let celIndPth = cellAttributes.indexPath

if celIndPth.item == 0
{ // YOU HAVE TO ADD SUPPLEMENTARY HEADER TO THIS LAYOUT ATTRIBUTES
if let supplementaryAttributes = layoutAttributesForSupplementaryView(ofKind: UICollectionElementKindSectionHeader, at: cellAttributes.indexPath) {
attributesInRect.append(supplementaryAttributes)
}

}

}
}

return attributesInRect
}

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {

return cellAttrsDictionary[indexPath]!

}

override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}

override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {

if elementKind == UICollectionElementKindSectionHeader {

let atts = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, with: indexPath)

if let itemAttributes = layoutAttributesForItem(at: indexPath) { // HERE WE HAVE TO SET FRAME FOR SUPPLEMENTARY VIEW

atts.frame = CGRect(x: itemAttributes.frame.origin.x,
y: itemAttributes.frame.origin.y - CGFloat(headerSpacing),width: itemAttributes.frame.width,height: CGFloat(headerSpacing))

return atts
}
}

return nil
}

}

XIB Subclass - [Collection Reusable View]

Sample Image

class RulesReusableView: UICollectionReusableView {

@IBOutlet weak var headLbl: UILabel!
}

UICollectionViewCell

class RulesCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var txtLbl: UILabel!
}

Portrait Output

Sample Image

Landscape Output

Sample Image

How to add a custom view after every 2 rows in a collectionView swift

My Code should be explanatory. I have set some values in viewdidload to get the kind of view you require.

Please see screenshot

import UIKit

class CollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

@IBOutlet weak var collectionView : UICollectionView!

let totalProducts = 21
let columnsPerRow = 2
let addAfterRows = 2

var celltoShowWithAds = 0

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.
let quot = (totalProducts/(columnsPerRow * addAfterRows))
print(quot)
celltoShowWithAds = totalProducts + quot + 1

collectionView.register(UINib(nibName: "CollectionItemCell", bundle: nil), forCellWithReuseIdentifier: "CollectionItemCell")

collectionView.register(UINib(nibName: "CollectionAdvertisementCell", bundle: nil), forCellWithReuseIdentifier: "CollectionAdvertisementCell")

collectionView.delegate = self
collectionView.dataSource = self
collectionView.reloadData()
//collectionView.backgroundColor = UIColor.blue
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return celltoShowWithAds

}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == 0{
let myCell:CollectionAdvertisementCell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionAdvertisementCell", for: indexPath) as! CollectionAdvertisementCell
return myCell as CollectionAdvertisementCell;

}else if indexPath.row % 5 == 0{
let myCell:CollectionAdvertisementCell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionAdvertisementCell", for: indexPath) as! CollectionAdvertisementCell

return myCell as CollectionAdvertisementCell;
}else{
let myCell:CollectionItemCell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionItemCell", for: indexPath) as! CollectionItemCell

return myCell as CollectionItemCell;
}

}

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

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.row == 0{
return CGSize(width: view.frame.width, height: 0.0)
}else if indexPath.row % 5 == 0 {
return CGSize(width: view.frame.width, height: 80.0)
}else{
return CGSize(width: view.frame.width/CGFloat(columnsPerRow), height: 200.0)
}

}

//Use for interspacing
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
}

/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/

}

UICollectionView Custom Layout Middle column starting higher

The Collection view layout can be achieved by creating a custom layout class.

Theory:

Basically, collection view works directly with the custom layout object to manage the overall layout process, asking for the required layout information.

During the layout process, the collection view calls specific methods of the layout object. These methods provide a chance to calculate the position of items and to provide the collection view with the primary information it needs.

Following methods are always called in order during the layout process:

  1. prepare(): Perform the up-front calculations needed to provide layout information
  2. collectionViewContentSize: Return the overall size of the entire content area based on your initial calculations
  3. layoutAttributesForElements(in:): Return the attributes for cells and views that are in the specified rectangle


Related Topics



Leave a reply



Submit