Infinite scrolling compositional layout Swift

Viewed 254

I am making an app that is using compositional layout for the collectionview I'm having a carrousel layout that display elements horizontally.

let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(100), heightDimension: .absolute(100))
    let item = NSCollectionLayoutItem(layoutSize: itemSize)
    item.contentInsets = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2)
    let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(100), heightDimension: .fractionalWidth(1 / 3))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
    group.contentInsets = .init(top: 4, leading: 0, bottom: 4, trailing: 0)
    let section = NSCollectionLayoutSection(group: group)
    section.orthogonalScrollingBehavior = .continuous

How can I achieve infinite scrolling meaning that every time we get the last element it goes back to the first element and continue to scroll? (for now it works, I can scroll element but every time the last element is displayed I have to scroll back the other way)

I have seen many way to achieve this with the old collectionview system, but I wanna keep using the new way please

1 Answers

Maintain your datasource and return Int16.max or any large number and do simple modulo to get your item from datasource to dequeue reusable cell with your model

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var collectionView: UICollectionView!

var sections: [Int] = Array(0...7)
var models: [[Int]] = Array(repeating: [1,2,3,4,5,6,7,8], count: 8)

var sectionCellColors: [Int: UIColor] = [
    0 : .blue,
    1 : .red,
    2 : .green,
    3 : .yellow,
    4 : .magenta,
    5 : .brown,
    6 : .gray,
    7 : .black
]

override func viewDidLoad() {
    super.viewDidLoad()
    collectionView.backgroundColor = .cyan
    let layout = createLayout()
    collectionView.setCollectionViewLayout(layout, animated: false)
}

func createLayout() -> UICollectionViewCompositionalLayout {
    let layout = UICollectionViewCompositionalLayout { sectionNum, environment in
        let item = NSCollectionLayoutItem(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(0.2),
                heightDimension: .fractionalHeight(1)))
        item.contentInsets = .init(top: 8, leading: 8, bottom: 8, trailing: 8)
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(300)), subitems: [item])
        let section = NSCollectionLayoutSection(group: group)
        section.orthogonalScrollingBehavior = .continuous
        return section
    }
    return layout
}

override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
    if context.nextFocusedView?.isKind(of: UICollectionViewCell.self) == true {
        context.nextFocusedView?.layer.borderColor = UIColor.purple.cgColor
        context.nextFocusedView?.layer.borderWidth = 2
    }
    if context.previouslyFocusedView?.isKind(of: UICollectionViewCell.self) == true {
        context.nextFocusedView?.layer.borderColor = UIColor.clear.cgColor
        context.nextFocusedView?.layer.borderWidth = 0
    }
}
}

extension ViewController: UICollectionViewDataSource {

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return Int(Int16.max)
//        return sections.count
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return models[section % sections.count].count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellID", for: indexPath)
    cell.backgroundColor = sectionCellColors[indexPath.section % sections.count]
    return cell
}
}
Related