UICollectionView showing 2 items instead of 3

1.4k views Asked by At

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

4

There are 4 answers

2
Svetoslav Bramchev On BEST ANSWER

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)
    }
0
Vikas Rajput On

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)
}
0
mag_zbc On

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)
}
0
Yuyutsu On

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)
    }
}