Search code examples
swiftuicollectionviewuikituicollectionviewlayout

UICollectionViewCompositionalLayout with groupPagingCentered doesn't start centered


My layout code is very simple, something that you will have seen in every tutorial or article about the new compositional layouts.

  func createLayout() -> UICollectionViewLayout {
    let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
    let item = NSCollectionLayoutItem(layoutSize: itemSize)
    item.contentInsets = .init(top: 0, leading: 5, bottom: 0, trailing: 5)

    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.93), heightDimension: .fractionalHeight(1.0))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])

    let section = NSCollectionLayoutSection(group: group)
    section.orthogonalScrollingBehavior = .groupPagingCentered

    let layout = UICollectionViewCompositionalLayout(section: section)
    return layout
  }

When I start the app, the cell is not properly centered. Only when I drag the cell by the tiniest amount, does it spring to its correct place.

Before:

enter image description here

After I drag it a tiny bit:

enter image description here

I have not seen any questions on SO about the same problem. Nobody on Twitter or in blogs talking about it. Not sure what I am doing wrong here?


Solution

  • Maybe too late, but here is a workaround:

    func createLayout() -> UICollectionViewLayout {
        let layout = UICollectionViewCompositionalLayout { (sectionIndex, environment) -> NSCollectionLayoutSection? in
            let sideInset: CGFloat = 5
    
            let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
            let item = NSCollectionLayoutItem(layoutSize: itemSize)
            item.contentInsets = .init(top: 0, leading: sideInset, bottom: 0, trailing: sideInset)
    
            let groupWidth = environment.container.contentSize.width * 0.93
            let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(groupWidth), heightDimension: .fractionalHeight(1.0))
            let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
    
            let section = NSCollectionLayoutSection(group: group)
    
            // add leading and trailing insets to the section so groups are aligned to the center
            let sectionSideInset = (environment.container.contentSize.width - groupWidth) / 2
            section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: sectionSideInset, bottom: 0, trailing: sectionSideInset)
    
            // note this is not .groupPagingCentered
            section.orthogonalScrollingBehavior = .groupPaging
    
            return section
        }
    
        return layout
    }