0

Hi Community I wanted to implement a UICollectionviewCell which have size of 110 and each row have 3 cells initially

1.) Now need to do some modification in such way firstRow should have 3 cells but the second should have 2 cells

2.) The first cells size should be 220 and second remains the same 110

3.) In the third row it will have same structure as first rows

4.) But in 4th row the first cell size will 110 and second will be 220

it will repeat in same structure for further data

I am able to design as 3 cells in each row but for rest I need help

  func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    let width = (self.view.frame.size.width - 12 * 3) / 3
    let height = width * 1.5
    return CGSize(width: width, height: height)
}
Sanjay Mishra
  • 672
  • 7
  • 17

2 Answers2

1

One approach is to implement sizeForItemAt.

You can determine whether the row should have 2 or 3 cells by using the modulo operator (%) like this:

let itemsPerRow: CGFloat = indexPath.item % 5 < 3 ? 3 : 2

This will give you a 3-2-3-2-3... pattern.

Here's a quick example...

We'll use this cell class - a single label, constrained 8-points on all four sides:

class SomeCell: UICollectionViewCell {
    let theLabel: UILabel = {
        let v = UILabel()
        v.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
        v.textAlignment = .center
        v.font = .systemFont(ofSize: 24.0, weight: .regular)
        return v
    }()
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        theLabel.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(theLabel)
        let g = contentView.layoutMarginsGuide
        NSLayoutConstraint.activate([
            theLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
            theLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
            theLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
            theLabel.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0),
        ])
    }
}

Then this view controller class:

class ThreeTwoViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let fl = UICollectionViewFlowLayout()
        fl.scrollDirection = .vertical
        fl.minimumLineSpacing = 12.0
        fl.minimumInteritemSpacing = 0.0
        fl.sectionInset = .init(top: 8.0, left: 8.0, bottom: 8.0, right: 8.0)
        
        let cv = UICollectionView(frame: .zero, collectionViewLayout: fl)
        cv.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(cv)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            cv.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            cv.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            cv.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            cv.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
        ])

        cv.register(SomeCell.self, forCellWithReuseIdentifier: "c")
        cv.dataSource = self
        cv.delegate = self
        
        cv.backgroundColor = .systemYellow
    }
}

extension ThreeTwoViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 30
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "c", for: indexPath) as! SomeCell
        cell.backgroundColor = .systemBlue
        cell.theLabel.text = "\(indexPath.item)"
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
        let itemsPerRow: CGFloat = indexPath.item % 5 < 3 ? 3 : 2
        
        var sidePadding: CGFloat = 0.0
        var itemPadding: CGFloat = 12.0
        
        if let fl = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            sidePadding = fl.sectionInset.left + fl.sectionInset.right
            if itemPadding < fl.minimumInteritemSpacing {
                itemPadding = fl.minimumInteritemSpacing
            }
        }
        
        let paddingSpace: CGFloat = itemPadding * (itemsPerRow - 1) + sidePadding
        let availableWidth: CGFloat = collectionView.frame.width - paddingSpace
        let widthPerItem: CGFloat = availableWidth / itemsPerRow
        
        let cellHeight: CGFloat = widthPerItem * 1.5

        return CGSize(width: widthPerItem, height: cellHeight)
    }
    
}

Which gives us this output:

enter image description here

DonMag
  • 69,424
  • 5
  • 50
  • 86
0
The Solution I found is 

      private func createGridLayout() -> UICollectionViewCompositionalLayout {
        
        // MARK: - Define the Item Layouts
            
            // Define layout for top cells (1/3 width)
        let topCellItemLayout = CompositionalLayout.createItemLayout(width: .fractionalWidth(1/3), height: .fractionalHeight(1.0), specing: 1)
            
            // Define layout for second cells (2/3 width)
        let secondCellItemLayout = CompositionalLayout.createItemLayout(width: .fractionalWidth(2/3), height: .fractionalHeight(1.0), specing: 1)
            
            // Define layout for single cells (full width)
        let singleCellItemLayout = CompositionalLayout.createItemLayout(width: .fractionalWidth(1.0), height: .fractionalHeight(1.0), specing: 1)
            
            // MARK: - Apply Content Insets
            
            // Apply content insets to top cell item layout
            topCellItemLayout.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5)
            
            // Apply content insets to second cell item layout
            secondCellItemLayout.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5)
            
            // Apply content insets to single cell item layout
            singleCellItemLayout.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5)
            
            // MARK: - Create Groups
        // Create group layout for top cells
        let topCellGroupLayout = CompositionalLayout.createGroupLayout(alignment: .horizontal, width: .fractionalWidth(1.0), height: .fractionalWidth(4/9), item: topCellItemLayout, count: 3)
            
            // Create group layout for single cells
        let singleCellGroupLayout = CompositionalLayout.createGroupLayout(alignment: .vertical, width: .fractionalWidth(1/3), height: .fractionalHeight(1.0), items: [singleCellItemLayout])
            
            // Create group layout for second cells and single cell group
        let secondCellGroupLayout = CompositionalLayout.createGroupLayout(alignment: .horizontal, width: .fractionalWidth(1.0), height: .fractionalWidth(4/9), items: [secondCellItemLayout, singleCellGroupLayout])
            
            // Create group layout for container with second cell and single cell groups
        let containerGroupsLayout = CompositionalLayout.createGroupLayout(alignment: .horizontal, width: .fractionalWidth(1.0), height: .fractionalWidth(4/9), items: [secondCellItemLayout, singleCellGroupLayout])
            
            // Create group layout for fourth container with single cell and second cell groups
        let fourthContainerGroupLayout = CompositionalLayout.createGroupLayout(alignment: .horizontal, width: .fractionalWidth(1.0), height: .fractionalWidth(4/9), items: [singleCellGroupLayout, secondCellItemLayout])
            
            // Create main container group layout with all the above group layouts
        let mainContainerGroupLayout = CompositionalLayout.createGroupLayout(alignment: .vertical, width: .fractionalWidth(1.0), height: .fractionalWidth(16/9), items: [topCellGroupLayout, secondCellGroupLayout, topCellGroupLayout, fourthContainerGroupLayout])
            
            // MARK: - Create Section
            
            // Create the section layout with the main container group layout
        let sectionLayout = NSCollectionLayoutSection(group: mainContainerGroupLayout)
            
            // MARK: - Return the Layout
            
            // Return the compositional layout with the section layout
        return UICollectionViewCompositionalLayout(section: sectionLayout)
    }
}





 enum CompositionalGroupAlignment {
    case vertical
    case horizontal
}
struct CompositionalLayout {
    
    static func createItemLayout(width: NSCollectionLayoutDimension, height: NSCollectionLayoutDimension, specing: CGFloat) -> NSCollectionLayoutItem {
        let item = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: width, heightDimension: height))
        item.contentInsets = NSDirectionalEdgeInsets(top: specing, leading: specing, bottom: specing, trailing: specing)
        return item
    }
    
    static func createGroupLayout(alignment: CompositionalGroupAlignment, width: NSCollectionLayoutDimension, height: NSCollectionLayoutDimension, items: [NSCollectionLayoutItem]) -> NSCollectionLayoutGroup {
        switch alignment {
        case .vertical:
            return NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: width, heightDimension: height), subitems: items)
        case .horizontal:
            return NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: width, heightDimension: height), subitems: items)
        }
    }
    
    static func createGroupLayout(alignment: CompositionalGroupAlignment, width: NSCollectionLayoutDimension, height: NSCollectionLayoutDimension, item: NSCollectionLayoutItem, count: Int) -> NSCollectionLayoutGroup {
        switch alignment {
        case .vertical:
    
            return NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: width, heightDimension: height), repeatingSubitem: item, count: count)
        case .horizontal:
            return NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: width, heightDimension: height), repeatingSubitem: item, count: count)
        }
    }
} 
Sanjay Mishra
  • 672
  • 7
  • 17