0

I'm currently trying to achieve the following layout using NSCollectionLayoutSection. Do you have any advice on only making the first item 50px wide while keeping the rest of the items 100px (could be any number of items)? The solution has to be an NSCollectionLayoutSection.

enter image description here

I'm currently displaying them in the same width using which is not the desired result:

    let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)))
    item.contentInsets = NSDirectionalEdgeInsets(top: 0,
                                                 leading: 0,
                                                 bottom: 0,
                                                 trailing: 8)
    
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .absolute(100),
                                             heightDimension: .absolute(100)), subitems: [item])
    
    let section = NSCollectionLayoutSection(group: group)
    section.contentInsets = NSDirectionalEdgeInsets(top: 16,
                                                   leading: 16,
                                                   bottom: 16,
                                                   trailing: 16)
    section.orthogonalScrollingBehavior = .continuous

enter image description here

I've also tried using absolute widths but didn't have much luck with that approach.

Thank you!

Kirill
  • 738
  • 10
  • 26

1 Answers1

2

You can achieve this by creating two separate item groups (one for the first cell which has a half width and second for the rest of the cells). Then combine those two groups and add it to the section.

class ViewController: UIViewController {

    @IBOutlet var collectionView: UICollectionView!
    
    let headerId = "headerId"
    let categoryHeaderId = "categoryHeaderId"
    let colorarray = [UIColor.yellow, UIColor.green, UIColor.green, UIColor.green, UIColor.green, UIColor.green, UIColor.green, UIColor.green]

    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationItem.title = "My Albums"
        collectionView.register(AlbumItemCell.self, forCellWithReuseIdentifier: AlbumItemCell.reuseIdentifer)
        collectionView.register(CategoryHeaderView.self, forSupplementaryViewOfKind: categoryHeaderId, withReuseIdentifier: headerId)
        collectionView.collectionViewLayout = createCompositionalLayout()
        collectionView.reloadData()
    }

    private func createCompositionalLayout() -> UICollectionViewCompositionalLayout {
        
        return UICollectionViewCompositionalLayout { (sectionNumber, env) -> NSCollectionLayoutSection? in
            self.firstLayoutSection()
        }
    }
    
    private func firstLayoutSection() -> NSCollectionLayoutSection {
        
        let cellWidth : CGFloat = 200
        let cellHeight : CGFloat = 200
        
        let smallItemSize = NSCollectionLayoutSize(widthDimension: .absolute(cellWidth/2), heightDimension: .absolute(cellHeight))
        let smallItem = NSCollectionLayoutItem(layoutSize: smallItemSize)
        let smallGroupSize = NSCollectionLayoutSize(widthDimension: .absolute(cellWidth/2), heightDimension: .absolute(cellHeight))
        let smallGroup = NSCollectionLayoutGroup.horizontal(layoutSize: smallGroupSize, subitem: smallItem, count: 1)
        smallGroup.contentInsets = .init(top: 0, leading: 8, bottom: 0, trailing: 8)
        
        
        let largeItemSize = NSCollectionLayoutSize(widthDimension: .absolute(cellWidth), heightDimension: .absolute(cellHeight))
        let largeItem = NSCollectionLayoutItem(layoutSize: largeItemSize)
        largeItem.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 8)
        let largeGroupSize = NSCollectionLayoutSize(widthDimension: .absolute(CGFloat((cellWidth + 8) * CGFloat((colorarray.count - 1)))), heightDimension: .absolute(cellHeight))
        let largeGroup = NSCollectionLayoutGroup.horizontal(layoutSize: largeGroupSize, subitem: largeItem, count: colorarray.count - 1 )

        
        let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(cellWidth * CGFloat(colorarray.count)), heightDimension: .absolute(cellHeight))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [smallGroup, largeGroup])
       
        let section = NSCollectionLayoutSection(group: group)
        section.orthogonalScrollingBehavior = .groupPaging
        
        return section
    }
    
}

extension ViewController: UICollectionViewDataSource {
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        colorarray.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: AlbumItemCell.reuseIdentifer, for: indexPath) as! AlbumItemCell
        cell.configure(color: colorarray[indexPath.row])
        return cell
    }
    
}

class AlbumItemCell: UICollectionViewCell {
    
  static let reuseIdentifer = "album-item-cell-reuse-identifier"
  let view = UIImageView()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        view.layer.cornerRadius = 10
        view.layer.masksToBounds = true
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func configure(color: UIColor) {
        view.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(view)
        NSLayoutConstraint.activate([
            view.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            view.topAnchor.constraint(equalTo: contentView.topAnchor),
            view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
        ])
        view.backgroundColor = color

    }
}

Result enter image description here

udi
  • 3,672
  • 2
  • 12
  • 33