Juri
Juri

Reputation: 93

How to setup different padding sizes for UICollectionViewCell

I would like to create a collection view to be like on the picture

enter image description here

SO far I do have this code for my controller

class MainCollController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate  {

let cellId = "collectionCellId"

override func viewDidLoad() {
    super.viewDidLoad()


    let flowLayout = UICollectionViewFlowLayout()
    let collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: flowLayout)
    collectionView.register(Cell.self, forCellWithReuseIdentifier: cellId)
    collectionView.delegate = self
    collectionView.dataSource = self
    collectionView.backgroundColor = UIColor.grayBg

    self.view.addSubview(collectionView)

    _ = collectionView.anchor(view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)

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

}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: view.frame.width / 2 , height: 280)
}

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

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! Cell
    cell.backgroundColor = UIColor.cyan
    cell.cellIndex = indexPath.row

    return cell
}

}

And this one for the cell. I was thinking to check if indexPath.row is even or add and depends on it set a different constraints.

class Cell: UICollectionViewCell {

var cellIndex: Int? {
    didSet {
        if cellIndex! % 2 == 0 {
            _ = productView.anchor(topAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 0, leftConstant: 20, bottomConstant: 0, rightConstant: 8.5, widthConstant: 0, heightConstant: 264)
        } else {
            _ = productView.anchor(topAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 0, leftConstant: 11.5, bottomConstant: 0, rightConstant: 19.5, widthConstant: 0, heightConstant: 264)
        }
    }
}

let productView: UIView = {
    let view = UIView()
    view.backgroundColor = UIColor.white
    view.layer.borderColor = UIColor(red:0.867, green:0.867, blue:0.867, alpha:1.000).cgColor
    view.layer.borderWidth = 0.5
    return view
}()

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

    addSubview(productView)

}

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

When I open my app it does look exactly how I need it to be, but when I start scrolling down and up everything gets mixed.

enter image description here

Can you please help me to sort it out. Thanks!

Upvotes: 0

Views: 122

Answers (3)

Nimish Sharma
Nimish Sharma

Reputation: 121

Try this code...


extension YourVC: UICollectionViewDelegateFlowLayout {

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


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

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

    let itemSpacing: CGFloat = 5 //set the spacing as needed
    let itemSize = (collectionView.frame.width - (3 * itemSpacing)) / 2

    return CGSize(width: itemSize, height: itemSize * 1.69)
}

}

Note: 1.69 is the height to width ratio that is have taken. (Means cell height is 1.69 times the width of itself.)

Upvotes: 1

matt
matt

Reputation: 535576

The layout you're trying to make, with fixed cell sizes and paddings and number of cells per row to form a regular grid, is not really what UICollectionViewFlowLayout is intended for. You'd be better off writing your own collection view layout, or at the very least subclassing UICollectionViewFlowLayout, to lay the cells out the way you want them.

Don't know how to get started? There are many grid layout examples out there that you can start with: do a Google search on "UICollectionView grid layout".

Upvotes: 1

Kingalione
Kingalione

Reputation: 4265

You need to implement these two functions to make a collectionView like you want:

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

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

Feel free to play with the values for your purpose.

Upvotes: 1

Related Questions