9

I have a UICollectionView created from storyboard,

I want to have 3 items per row in the view. I managed to do that using the following:

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(collectionView.frame.size.width/3.6 , (collectionView.frame.size.height-100)/2);
}

However, if i have 6 items, i got 2 rows with 3 items each. But when i have 4 items, it will display 2 rows with 2 items each.

Is it possible to display them in 2 rows, the first with 3 items and the second contains only 1?

Iphone User
  • 1,930
  • 2
  • 17
  • 26
  • Try This link [http://stackoverflow.com/questions/14674986/uicollectionview-set-number-of-columns](http://stackoverflow.com/questions/14674986/uicollectionview-set-number-of-columns) – Prashant Tukadiya Dec 06 '15 at 10:21
  • @PrashantTukadiya nothing i could use, it is still showing 2 rows with 2 items each, and an empty space on the right (which fit a cell on the first row) – Iphone User Dec 06 '15 at 10:33
  • try this one http://stackoverflow.com/questions/17229350/cell-spacing-in-uicollectionview – Prashant Tukadiya Dec 06 '15 at 10:35
  • What value have you set for the spacing between cells and lines of the collection view in your storyboard? – Adeel Miraj Dec 06 '15 at 13:59
  • @AdeelMiraj 10 for each – Iphone User Dec 06 '15 at 14:19
  • Does it happen on every device/simulator or on some specific screen sizes? I also had this problem and it happened only on the screens 320 pts wide. – Adeel Miraj Dec 06 '15 at 14:54
  • Just try reducing the spacing between the cells and see if it resolves the problem or not. – Adeel Miraj Dec 06 '15 at 14:57
  • @AdeelMiraj it is happening on all devices, i tried to set it to 0 and still the same – Iphone User Dec 06 '15 at 16:08
  • Use these delegate methods to check the frame of the cells for both the scenarios that you mentioned. 1) - `collectionView:willDisplayCell:forItemAtIndexPath:` 2) - `collectionView:didEndDisplayingCell:forItemAtIndexPath:` – Adeel Miraj Dec 06 '15 at 16:38

8 Answers8

13

here i did it , i implemented UICollectionViewDelegateFlowLayout on UICollectionView add following method . it work , use it .

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenWidth = screenRect.size.width;
    float cellWidth = screenWidth / 3.0; //Replace the divisor with the column count requirement. Make sure to have it in float.
    CGSize size = CGSizeMake(cellWidth, cellWidth);

    return size;
}

this method work as screen size width divided by 3 .

Hiren Dhamecha
  • 658
  • 5
  • 15
  • try to have only 4 items, it will display them as 2 rows and each row with 2 cells, I have already tried it – Iphone User Dec 06 '15 at 10:51
  • here , CGSize size =CGSizeMake(100,100) in give deault value and try it .. (if you can try in iphone 6 or greater then give condtion for resolution and set size) – Hiren Dhamecha Dec 06 '15 at 11:29
  • it is not related to the phone, when i have 6 items all is perfect, but when it is 4 items the collection arrange the items to have the same number in each row, i dont know if it is normal or i could change it in a way – Iphone User Dec 06 '15 at 12:14
  • see this link : http://stackoverflow.com/questions/14674986/uicollectionview-set-number-of-columns Try it – Hiren Dhamecha Dec 06 '15 at 12:23
3

Easiest way

Objc version

UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout*)collectionView.collectionViewLayout;
flowLayout.sectionInset = UIEdgeInsetsMake(15, 15, 15, 15);

NSInteger itemRowCount = 3;
CGFloat rowWidth = collectionView.contentSize.width -  flowLayout.sectionInset.left - flowLayout.sectionInset.right;
CGFloat itemWidth = (rowWidth - flowLayout.minimumInteritemSpacing * (itemRowCount - 1) ) / itemRowCount;
CGFloat itemHeight = itemWidth / 3;
flowLayout.itemSize = CGSizeMake(itemWidth, itemHeight);

Swift version

if let flowLayout = contentCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
    flowLayout.sectionInset = .init(top: 12, left: 16, bottom: 12, right: 16)
    
    let itemRowCount: CGFloat = 3
    
    let rowWidth: CGFloat = contentCollectionView.contentSize.width - flowLayout.sectionInset.left - flowLayout.sectionInset.right
    let allInterSpaceWidth: CGFloat = flowLayout.minimumInteritemSpacing * (itemRowCount - 1)
    let itemWidth: CGFloat = (rowWidth - allInterSpaceWidth ) / itemRowCount
    
    let itemWidthHeightRatio = itemWidth / 3
    let itemHeight: CGFloat = itemWidth * itemWidthHeightRatio
    
    flowLayout.itemSize = .init(width: itemWidth, height: itemHeight)
}
Jadian
  • 4,144
  • 2
  • 13
  • 10
2
(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
  CGRect screenRect = [[UIScreen mainScreen] bounds];
  CGFloat screenWidth = screenRect.size.width;
  float cellWidth = screenWidth / 3.2; //Replace the divisor with the column count requirement. Make sure to have it in float.
  CGFloat screenHeight = screenRect.size.height;
  float cellHeight = screenHeight/3.0;


  CGSize size = CGSizeMake(cellWidth, cellHeight);


  return size;
}

Apply the below code too-(viewWillTransitionToSize)

(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
  [self.collectionView/*(that's my collection view name)*/ reloadData];
}

This Code will help to get the same no. of cells in portrait as well as in landscape mode also. I have applied above code to get 3 cells in portrait as well as 3 cells in landscape mode.

michael_bitard
  • 3,613
  • 1
  • 24
  • 35
Shashwat Tyagi
  • 255
  • 5
  • 15
1

try this

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(self.view.frame.size.width/3 -10 , (collectionView.frame.size.height-100)/2);
}
KKRocks
  • 8,222
  • 1
  • 18
  • 84
1
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    return CGSizeMake(self.collectionView.bounds.size.width/3, self.collectionView.bounds.size.width/3);
}

Most important thing need to do as well is in size inspector of collectionView set up the minimum spacing for cell & line to 0

DaFois
  • 2,197
  • 8
  • 26
  • 43
Paul.V
  • 386
  • 1
  • 3
  • 13
1

You need to calculate first the available space for the content and then divide that by the number of items you want to present per row.

Here is an example assuming that the UICollectionView is taking all the width of the screen

private let numberOfItemPerRow = 2

private let screenWidth = UIScreen.main.bounds.width
private let sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
private let minimumInteritemSpacing = CGFloat(10)
private let minimumLineSpacing = CGFloat(10)

// Calculate the item size based on the configuration above  
private var itemSize: CGSize {
    let interitemSpacesCount = numberOfItemPerRow - 1
    let interitemSpacingPerRow = minimumInteritemSpacing * CGFloat(interitemSpacesCount)
    let rowContentWidth = screenWidth - sectionInset.right - sectionInset.left - interitemSpacingPerRow

    let width = rowContentWidth / CGFloat(numberOfItemPerRow)
    let height = width // feel free to change the height to whatever you want 

    return CGSize(width: width, height: height)
}
Alaeddine
  • 6,104
  • 3
  • 28
  • 45
-1

Swift 5

flowLayout.aspectRatio = 1
flowLayout.sectionInset = UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2)
flowLayout.interitemSpacing = 10
flowLayout.lineSpacing = 10
flowLayout.numberOfItemsPerLine = 4
flowLayout.scrollDirection = .vertical
self.collectionView.collectionViewLayout = flowLayout```

You can find KRLCollectionViewGridLayout library here -(https://github.com/klundberg/KRLCollectionViewGridLayout)
Moban
  • 1
  • 2
-2

I know it is so late, but the solution that i am currently using and handled this case was by using KRLCollectionViewGridLayout as below

        KRLCollectionViewGridLayout* aFlowLayout = [[KRLCollectionViewGridLayout alloc]init];
        aFlowLayout.aspectRatio = 1;
        aFlowLayout.sectionInset = UIEdgeInsetsMake(2, 2, 2, 2);
        aFlowLayout.interitemSpacing = 2;
        aFlowLayout.lineSpacing = 2;
        aFlowLayout.numberOfItemsPerLine = 3;
        aFlowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;

        _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width,self.view.frame.size.heigh) collectionViewLayout:aFlowLayout];

You can find KRLCollectionViewGridLayout library class using this link

Iphone User
  • 1,930
  • 2
  • 17
  • 26