0

I have implemented my UICollectionView like this

extension MyViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

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

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath)
        cell.backgroundColor = .black
        return cell
    }
}

extension MyViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
        let widthPerItem = view.frame.width / 3
        return CGSize(width: widthPerItem, height: widthPerItem)
    }
}

but instead of 3 items in a row I'm getting 2 items enter image description here

how can i fix it? i didn't set any UIEdgeInset for my items and sections

Amir_P
  • 8,322
  • 5
  • 43
  • 92

4 Answers4

1

You forgot to account for minimumInteritemSpacing and minimumLineSpacing properties of UICollectionViewFlowLayout - they both default to 10.0 if you didn't set them.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let spacing : CGFloat = (collectionViewLayout as? UICollectionViewFlowLayout)?.minimumInteritemSpacing ?? 0.0
    let widthPerItem = (view.frame.width  - spacing * 2)/ 3
    return CGSize(width: widthPerItem, height: widthPerItem)
}
Amir_P
  • 8,322
  • 5
  • 43
  • 92
mag_zbc
  • 6,801
  • 14
  • 40
  • 62
1

Try this:

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

        let numRowItems:CGFloat = 3
        let padding:CGFloat = 2
        let width = (collectionView.bounds.width / numRowItems) - padding 
        let height = collectionView.bounds.height - (2 * padding)
        return CGSize(width: width, height: height)
    }
}
Yuyutsu
  • 2,509
  • 22
  • 38
0

This is because your screan width can not fit 3 cells. This is because collection view has cell min line spacing property in your storyboard if you try with small width in sizeForItemAt they will fit.

  func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
        let widthPerItem = view.frame.width / 3 - ((collectionViewLayout as? UICollectionViewFlowLayout)?.minimumInterItemSpacing ?? 0.0)
        return CGSize(width: widthPerItem, height: widthPerItem)
    }
  • In your method sizeForItemAt you set other minimum size. Change this size and it will work. Because if you implement this method values from this method are preferd than these from storyboard – Svetoslav Bramchev Aug 29 '17 at 11:14
  • Will this even compile? You're trying to subtract `Optional` from `CGFloat` – mag_zbc Aug 29 '17 at 11:29
-1

in obj c

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

//If you want your cell should be square in size the return the equal height and width, and make sure you deduct the Section Inset from it.
return CGSizeMake((self.view.frame.size.width/2) - 16, (self.view.frame.size.width/2) - 16);
}

swift

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// Compute the dimension of a cell for an NxN layout with space S between
// cells.  Take the collection view's width, subtract (N-1)*S points for
// the spaces between the cells, and then divide by N to find the final
// dimension for the cell's width and height.

let cellsAcross: CGFloat = 3
let spaceBetweenCells: CGFloat = 1
let dim = (collectionView.bounds.width - (cellsAcross - 1) * spaceBetweenCells) / cellsAcross
return CGSize(width: dim, height: dim)
}
Vikas Rajput
  • 1,754
  • 1
  • 14
  • 26