Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create 2 x 2 grid layout using Collection View?

I am trying to create 2x2 grid layout using collection view.

I have used below code. It's kind of working fine for iPhone 5 but with tweaks. I am trying to write code that can be used on all screen sizes. This is not working on iPhone 6.

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

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

    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        if let cell1 = cell as? CollectionViewCell {
            return cell1
        }
        return cell
    }

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

        let padding: CGFloat =  20
        let collectionViewSize = collectionView.frame.size.width - padding

        return CGSize(width: collectionViewSize/2, height: collectionViewSize/2+15)
    }

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

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

    }

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

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

I am trying to achieve following layout: Expected

In future this grid can be like 2 columns only and N rows. Each row will always have 2 items.

like image 804
user3113946 Avatar asked Sep 19 '19 09:09

user3113946


2 Answers

First of all, get three variables together depending on your needs. Those are the minimum spacing (Both InteritemSpacing and Line spacing - Should be same UXwise but you can change that in delegate methods if you like. The interitem space however must always be equal to minimumSpacing), edgeInsetPadding and the number of items you want in a row.

private var numberOfItemsInRow = 2

private var minimumSpacing = 5

private var edgeInsetPadding = 10

In your code, you have already defined your Edge Insets as:

 UIEdgeInsets(
            top: 5, left: 5, bottom: 5, right: 5
        )

The left and right insets are important for correctly determining the size of the item. left+right gives us a grand sum of 10. This should be assigned to edgeInsetPadding like this:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let inset = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
        edgeInsetPadding = inset.left+inset.right
        return inset
    }

Now lets get to your UICollectionViewDelegateFlowLayout. Update the following methods.

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

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

Now lets get to the main part. Modify your sizeForItemAt in UICollectionViewDelegateFlowLayout as:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width = (Int(UIScreen.main.bounds.size.width) - (numberOfItemsInRow - 1) * minimumSpacing - edgeInsetPadding) / numberOfItemsInRow
        return CGSize(width: width, height: width)
    }

And this is it. You now get two equal size tiles in 2x2 grid. If you want to change this in future, just change the numberOfItemsInRow variable to something else. Like 3 for 3x3.

like image 193
NSNoob Avatar answered Nov 20 '22 15:11

NSNoob


This will be done using the item size of the collectionViewCell

collectionView.delegate = self 
extension ViewController : UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let padding = 5
        let width = (collectionView.frame.size.width - CGFloat(padding) * 2) / CGFloat(2)
        let height = width / 200 * 110 // or what height you want to do
        return CGSize(width: width, height: height)
    }
}

like image 25
Ankur Lahiry Avatar answered Nov 20 '22 17:11

Ankur Lahiry