128

I am trying to implement a CollectionView. When I am using Autolayout, my cells won't change the size, but their alignment.

Now I would rather want to change their sizes to e.g.

//var size = CGSize(width: self.view.frame.width/10, height: self.view.frame.width/10)

I tried setting in my CellForItemAtIndexPath

collectionCell.size = size

it didn't work though.

Is there a way to achieve this?

edit:

It seems, that the answers will only change my CollectionView width and height itself. Is there are conflict in Constraints possible? Any ideas on that ?

Jack
  • 10,795
  • 4
  • 65
  • 90
JVS
  • 1,994
  • 3
  • 16
  • 28

21 Answers21

355

Use this method to set custom cell height width.

Make sure to add this protocols

UICollectionViewDelegate

UICollectionViewDataSource

UICollectionViewDelegateFlowLayout

If you are using swift 5 or xcode 11 and later you need to set Estimate Size to none using storyboard in order to make it work properly. If you will not set that than below code will not work as expected.

enter image description here

Swift 4 or Later

extension YourViewController: UICollectionViewDelegate {
    //Write Delegate Code Here
}

extension YourViewController: UICollectionViewDataSource {
    //Write DataSource Code Here
}

extension YourViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: screenWidth, height: screenWidth)
    }
}

Objective-C

@interface YourViewController : UIViewController<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(CGRectGetWidth(collectionView.frame), (CGRectGetHeight(collectionView.frame)));
}
PinkeshGjr
  • 7,088
  • 5
  • 35
  • 52
  • I am searching for Swift code. I'm not sure how to transform this. – JVS Jun 25 '16 at 11:57
  • check this one now – PinkeshGjr Jun 25 '16 at 12:01
  • somehow it doesn't change my cells, but more like my CollectionView – JVS Jun 25 '16 at 12:03
  • you also need to set cell property to custom from storyboard design – PinkeshGjr Jun 25 '16 at 12:05
  • Unfortunately still changes the CollectionView size – JVS Jun 25 '16 at 12:10
  • set this cell.contentView.frame = cell.bounds; cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; – PinkeshGjr Jun 25 '16 at 12:13
  • @PinkeshGjr Bro how to support multi language in ios app. – Harshad Pansuriya Mar 31 '17 at 08:44
  • - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return CGSizeMake(CGRectGetWidth(collectionView.frame)/4, (CGRectGetHeight(collectionView.frame)/4)); } – Rahul K Rajan Jul 06 '17 at 06:12
  • see this question : https://stackoverflow.com/questions/45296759/when-app-in-background-and-receiving-push-notification-tap-app-goes-crash?noredirect=1#comment77555738_45296759 – Harshad Pansuriya Jul 25 '17 at 08:04
  • how to set cell's childs width height here? – user924 Feb 26 '18 at 11:10
  • Please explain your scenario properly – PinkeshGjr Feb 26 '18 at 11:12
  • The method is in _UICollectionViewDelegateFlowLayout_. It doesn't make sense to conform to 3 protocols in the same extension just for a single method that doesn't conform to the other 2 protocols. – Ramy Al Zuhouri May 06 '19 at 10:21
  • @RamyAlZuhouri do you think everyone is smart enough to add Delegate and DataSource ? Those who are new to iOS technology they might don't know much in details that's why i have added all protocols. – PinkeshGjr May 06 '19 at 10:24
  • @PinkeshGjr The question is not about the delegate and the data source, but about the layout specifically. Also, if they are added, they should be in another extension in order to avoid confusion. – Ramy Al Zuhouri May 06 '19 at 10:28
  • 1
    @RamyAlZuhouri Edited my answer please check and let me know if we still need to make it more clear – PinkeshGjr May 06 '19 at 10:31
  • 11
    I'm so used to doing everything programmatically that this seems so foreign to me now. In Storyboard setting **Estimated Size** to **None** and adding the **UICollectionViewDelegateFlowLayout** is what does the trick – Lance Samaria Jan 22 '20 at 13:37
  • 7
    Setting Estimate Size to none worked for me. Thank you @PinkeshGjr – Mohan Jan 27 '20 at 10:15
  • 7
    i'm glad i found this, i wasted 2 hours chasing this only to learn the magical 'Estimate Size to none' – Klajd Deda Feb 26 '20 at 19:24
  • 5
    set Estimate Size to none saved my days. – tounaobun Apr 01 '20 at 01:52
  • 1
    I just wanted to tell you, that you are a lifesaver! Thank you so much – Lennart P. May 23 '20 at 13:25
  • It's work for me. neigher the storyboard's Cell Size in collectionView nor item size's setting in protocol don't work, as long as set the estimate size automatic – 张富城 Oct 26 '20 at 01:52
  • Wow, works like a charm. *But* can someone please explain **WHY** we have to set `Estimate Size` to `None`........? – Eric Apr 26 '21 at 23:20
75

Make sure to add the protocol UICollectionViewDelegateFlowLayout in your class declaration

class MyCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout
{
    //MARK: - UICollectionViewDelegateFlowLayout

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
    {
       return CGSize(width: 100.0, height: 100.0)
    }
}
Jack
  • 10,795
  • 4
  • 65
  • 90
pierre23
  • 3,447
  • 1
  • 25
  • 24
75

If one is using storyboard and overriding UICollectionViewDelegateFlowLayout then in swift 5 and Xcode 11 also set Estimate size to None enter image description here

Spydy
  • 2,147
  • 17
  • 14
  • 2
    That was helpful. Thanks!! – Naval Hasan Dec 06 '19 at 05:39
  • That was definitely what I was about to crazy. Unless you set it to none, you are unable to see the correct size that you have given in sizeForItem method. – Yusuf Kamil AK Dec 28 '19 at 12:51
  • Lifesaver! It drove me crazy for hours! – nayem Jan 22 '20 at 12:32
  • 4
    Setting estimate size to none fixed everything – MMK Jan 31 '20 at 11:32
  • 2
    Thnx setting estimate size to none fixed by problem – Salman500 Feb 15 '20 at 20:52
  • OH GOD, THANK YOU! – R.Radev Mar 07 '20 at 19:42
  • Saved my life, thank you so much. But thats stupid i think. – Cemal BAYRI May 23 '20 at 22:03
  • 3
    Good fix. Here's my diagnosis of this issue according to [Apple's documentation](https://developer.apple.com/documentation/uikit/uicollectionviewflowlayout/1779556-automaticsize): `UICollectionViewFlowLayout` seems to default `estimatedItemSize` to `UICollectionViewFlowLayout.automaticSize` when using IB even though the documentation says it should default to `CGSizeZero`. As Apple states, `automaticSize` "enables self-sizing cells for your collection view." That's why other size changes in IB do nothing. – Andrew Kirna Jun 18 '20 at 21:02
  • 1
    just saved me hours I've been trying to find a fix forever – Ray Ray Jul 01 '20 at 09:02
21

Finally got the answer. You should extend UICollectionViewDelegateFlowLayout
This should be working with answers above.

AnthoPak
  • 3,531
  • 3
  • 18
  • 34
saburo
  • 269
  • 3
  • 12
  • Could you write an example? – Mamdouh El Nakeeb Oct 02 '17 at 21:45
  • Actually I made an extension with both datasource and delegateFlowLayout protocols and it did not work. What worked was separating the FlowLayout part to an extension of its own. Not sure why but it worked in swift 3. – Skywalker May 21 '18 at 02:35
16

Swift 4

You have 2 ways in order to change the size of CollectionView.
First way -> add this protocol UICollectionViewDelegateFlowLayout
for In my case I want to divided cell into 3 part in one line. I did this code below

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource ,UICollectionViewDelegateFlowLayout{
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
    {
            // In this function is the code you must implement to your code project if you want to change size of Collection view
            let width  = (view.frame.width-20)/3
            return CGSize(width: width, height: width)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return collectionData.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath)
        if let label = cell.viewWithTag(100) as? UILabel {
            label.text = collectionData[indexPath.row]
        }
        return cell
    }
}

Second way -> you don't have to add UICollectionViewDelegateFlowLayout but you have to write some code in viewDidload function instead as code below

class ViewController: UIViewController {
@IBOutlet weak var collectionView1: UICollectionView!
        var collectionData = ["1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10.", "11.", "12."]

    override func viewDidLoad() {
        super.viewDidLoad()
        let width = (view.frame.width-20)/3
        let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
        layout.itemSize = CGSize(width: width, height: width) 
    }
}

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
   

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return collectionData.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath)
        if let label = cell.viewWithTag(100) as? UILabel {
            label.text = collectionData[indexPath.row]
        }
   
        return cell
    }
}

Whatever you write a code as the first way or second way you will get the same result as above. I wrote it. It worked for me

enter image description here

craft
  • 1,448
  • 1
  • 12
  • 26
Sup.Ia
  • 187
  • 1
  • 7
13

Size ratio according to iPhone size :

Here's what you can do to have different width and height for cell's regarding the iPhone size :

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    let width = (self.view.frame.size.width - 12 * 3) / 3 //some width
    let height = width * 1.5 //ratio
    return CGSize(width: width, height: height)
}

And maybe you should also disable your AutoLayout constraints on cell for this answer to work.

Community
  • 1
  • 1
AnthoPak
  • 3,531
  • 3
  • 18
  • 34
  • I tried this and all the above solutions but the contents in a cell are not autoresizing, how can I fix this – Biasi Wiga Feb 20 '20 at 11:41
8

in Swift3 and Swift4 you can change cell size by adding UICollectionViewDelegateFlowLayout and implementing it's like this :

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 100, height: 100)
    }

or if create UICollectionView programmatically you can do it like this :

    let layout = UICollectionViewFlowLayout()
                    layout.scrollDirection = .horizontal //this is for direction
                    layout.minimumInteritemSpacing = 0 // this is for spacing between cells
                    layout.itemSize = CGSize(width: view.frame.width, height: view.frame.height) //this is for cell size
let collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)
Mohsen mokhtari
  • 2,115
  • 1
  • 21
  • 28
7

The collection view has a layout object. In your case, it is probably a flow layout (UICollectionViewFlowLayout). Set the flow layout's itemSize property.

matt
  • 447,615
  • 74
  • 748
  • 977
  • Tried this. gives me the same issue like before. somehow my CollectionView changes it size rather than my cells. – JVS Jun 25 '16 at 14:01
  • 2
    Well, it all depends _when_ you do it. You have not shown your real code, so who knows what you're doing? I assure you it does work. – matt Jun 25 '16 at 15:25
5

swift4 swift 4 ios collection view collectionview example xcode latest code working sample

Add this on Delegate section of the top

UICollectionViewDelegateFlowLayout

and use this function

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = (self.view.frame.size.width - 20) / 3 //some width
    let height = width * 1.5 //ratio
    return CGSize(width: width, height: height)
}

///// sample complete code

create on collection view and collectionview cell in storyboard give reference to the collection as
@IBOutlet weak var cvContent: UICollectionView!

paste this in View controller

 import UIKit

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    var arrVeg = [String]()
    var arrFruits = [String]()
    var arrCurrent = [String]()
    
    @IBOutlet weak var cvContent: UICollectionView!
    
  
    
    override func viewDidLoad() {
        super.viewDidLoad()
        arrVeg = ["Carrot","Potato", "Tomato","Carrot","Potato", "Tomato","Carrot","Potato", "Tomato","Carrot","Potato", "Tomato"]
        
        arrVeg = ["Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange"]
        
        
        arrCurrent = arrVeg
    }
    //MARK: - CollectionView
    


    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width = (self.view.frame.size.width - 20) / 3 //some width
        let height = width * 1.5 //ratio
        return CGSize(width: width, height: height)
    }
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {

        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
        
        return arrCurrent.count
    }
    
    
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ContentCollectionViewCell
        cell.backgroundColor =  UIColor.green
        return cell
    }
}
Harshad Pansuriya
  • 17,218
  • 7
  • 58
  • 86
Ullas Pujary
  • 281
  • 4
  • 12
3

Try below method

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSize(width: 100.0, height: 100.0)
}
Nilesh Patel
  • 6,060
  • 1
  • 23
  • 40
3

Swift 5 Programmatically

lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal

        //Provide Width and Height According to your need
        let cellWidth = UIScreen.main.bounds.width / 10
        let cellHeight = UIScreen.main.bounds.height / 10
        layout.itemSize = CGSize(width: cellWidth, height: cellHeight)

        //You can also provide estimated Height and Width
        layout.estimatedItemSize = CGSize(width: cellWidth, height: cellHeight)

        //For Setting the Spacing between cells
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0

        return UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
    }()
Shubham Mishra
  • 1,107
  • 10
  • 24
1

An other way is to set the value directly in the flow layout

    let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: size, height: size)
Antzi
  • 11,625
  • 6
  • 40
  • 66
1

Swift 5

Add these protocols

 - `UICollectionViewDelegate`
   
   
 - `UICollectionViewDataSource`
   
 
 - `UICollectionViewDelegateFlowLayout`

Your code will then look like this

extension YourViewController: UICollectionViewDelegate {
    //Write Delegate Code Here
}

extension YourViewController: UICollectionViewDataSource {
    //Write DataSource Code Here
}

extension YourViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: screenWidth, height: screenWidth)
    }
}

Now the final and crucial step to see this take effect is to go to your viedDidLoad function inside your Viewcontroller.

    override func viewDidLoad() {
        super.viewDidLoad()
        collection.dataSource = self // Add this
        collection.delegate = self // Add this
        
        // Do any additional setup after loading the view.
    }

Without telling your view which class the delegate is it won't work.

craft
  • 1,448
  • 1
  • 12
  • 26
Taka
  • 23
  • 1
  • 8
1

Absolutely simple way:

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource {

You must add "UICollectionViewDelegateFlowLayout" or, there is no autocomplete:

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {

Type "sizeForItemAt...". You're done!

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {
 
     func collectionView(_ collectionView: UICollectionView,
      layout collectionViewLayout: UICollectionViewLayout,
      sizeForItemAt indexPath: IndexPath) -> CGSize {
     
     return CGSize(width: 37, height: 63)
}

That's it.

Example, if you want "each cell fills the whole collection view":

     guard let b = view.superview?.bounds else { .. }
     return CGSize(width: b.width, height: b.height)
Fattie
  • 30,632
  • 54
  • 336
  • 607
0

A simple way:

If you just need a simple fixed size:

class SizedCollectionView: UIICollectionView {
    override func common() {
        super.common()
        let l = UICollectionViewFlowLayout()
        l.itemSize = CGSize(width: 42, height: 42)
        collectionViewLayout = l
    }
}

That's all there is to it.

In storyboard, just change the class from UICollectionView to SizedCollectionView.

But !!!

Notice the base class there is "UI 'I' CollectionView". 'I' for Initializer.

It's not that easy to add an initializer to a collection view. Here's a common approach:

Collection view ... with initializer:

import UIKit

class UIICollectionView: UICollectionView {
    private var commoned: Bool = false
    
    override func didMoveToWindow() {
        super.didMoveToWindow()
        if window != nil && !commoned {
            commoned = true
            common()
        }
    }
    
    internal func common() {
    }
}

In most projects, you need "a collection view with an initializer". So you will probably anyway have UIICollectionView (note the extra I for Initializer!) in your project.

Community
  • 1
  • 1
Fattie
  • 30,632
  • 54
  • 336
  • 607
0

So you need to setting from storyboard for attribute for collectionView in cell section estimate Size to none, and in your ViewController you need had delegate method for implementing this method : optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize

dgalluccio
  • 11
  • 4
0

Try to use UICollectionViewDelegateFlowLayout method. In Xcode 11 or later, you need to set Estimate Size to none from storyboard.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 
UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let padding: CGFloat =  170
    let collectionViewSize = advertCollectionView.frame.size.width - padding
    return CGSize(width: collectionViewSize/2, height: collectionViewSize/2)
}
0

Swift 5, Programmatic UICollectionView setting Cell width and height

// MARK: MyViewController

final class MyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
    private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
        let layout = UICollectionViewFlowLayout()
        let spacing: CGFloat = 1
        let numOfColumns: CGFloat = 3
        let itemSize: CGFloat = (UIScreen.main.bounds.width - (numOfColumns - spacing) - 2) / 3
        layout.itemSize = CGSize(width: itemSize, height: itemSize)
        layout.minimumInteritemSpacing = spacing
        layout.minimumLineSpacing = spacing
        layout.sectionInset = UIEdgeInsets(top: spacing, left: spacing, bottom: spacing, right: spacing)
        return layout
    }()
    
    private lazy var collectionView: UICollectionView = {
        let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: collectionViewLayout)
        collectionView.backgroundColor = .white
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureCollectionView()
    }
    
    private func configureCollectionView() {
        view.addSubview(collectionView)
        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
        ])
        collectionView.register(PhotoCell.self, forCellWithReuseIdentifier: "PhotoCell")
    }
    
    // MARK: UICollectionViewDataSource

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCell
        cell.backgroundColor = .red
        return cell
    }
    
}

// MARK: PhotoCell

final class PhotoCell: UICollectionViewCell {
    
    lazy var imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.layer.masksToBounds = true
        return imageView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init?(coder:) not implemented")
    }
    
    func setupViews() {
        addSubview(imageView)
        NSLayoutConstraint.activate([
            topAnchor.constraint(equalTo: topAnchor),
            bottomAnchor.constraint(equalTo: bottomAnchor),
            leadingAnchor.constraint(equalTo: leadingAnchor),
            trailingAnchor.constraint(equalTo: trailingAnchor)
        ])
    }
    
}
Suhit Patil
  • 10,286
  • 2
  • 42
  • 54
0

If, like me, you need to keep your custom flow layout's itemSize dynamically updated based on your collection view's width, you should override your UICollectionViewFlowLayout's prepare() method. Here's a WWDC video demoing this technique.

class MyLayout: UICollectionViewFlowLayout {
    
    override func prepare() {
        super.prepare()
        
        guard let collectionView = collectionView else { return }
        
        itemSize = CGSize(width: ..., height: ...)
    }
    
}
mattsven
  • 19,239
  • 8
  • 62
  • 102
0

If you are not using UICollectionViewController, you need to add conformance to it by setting delegates UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout.

  extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout

After that, you have to set a delegate to your collection view that is added to ViewController.

  collectionView.delegate = self
  collectionView.dataSource = self


  

And finally, you have to add layout to your collection view:

  let collectionLayout = UICollectionViewFlowLayout()
  collectionView.collectionViewLayout = collectionLayout

After these steps, you can change size in func:

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

This is my version, find your suitable ratio to get the cell size as per your requirement.

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
return CGSizeMake(CGRectGetWidth(collectionView.frame)/4, CGRectGetHeight(collectionView.frame)/4); 
} 
Rahul K Rajan
  • 748
  • 10
  • 19