无限滚动排版Swift

t2a7ltrp  于 2022-10-31  发布在  Swift
关注(0)|答案(2)|浏览(183)

我正在做一个应用程序,这是使用组合布局的收藏视图,我有一个旋转布局,显示水平元素。

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

我如何才能实现无限滚动,这意味着每次我们得到最后一个元素,它会回到第一个元素,并继续滚动?(现在它的工作,我可以滚动元素,但每次显示最后一个元素,我必须向后滚动的另一种方式)
我已经看到了许多方法来实现这一点与旧的收藏视图系统,但我想继续使用新的方式,请

vbkedwbf

vbkedwbf1#

维护您的数据源,返回Int16.max或任何较大的数字,并执行简单的取模操作,以便将数据源中的项与模型中的可重用单元格一起出队

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
}
}
fdbelqdn

fdbelqdn2#

首先,您必须向imagesArray中再添加2个图像,如下所示:

guard let firstImage = images.first, let lastImage = images.last else { return }
images.append(firstImage)
images.insert(lastImage, at: 0)

这样您就可以得到dataSource中相应图像我们使用scrollViewDidScroll方法和UICollectionView来实现无限滚动但是带有orthogonalScrollingBehavior节不响应此方法,因此您必须使用visibleItemsInvalidationHandler
您可以通过以下代码来实现这一点:

section.visibleItemsInvalidationHandler = { [weak self] _, point, _ in
    guard let self = self else { return }
    guard self.isHorizontalScrollingEnabled else { return }

    if point.x <= .zero {
        self.collectionView.scrollToItem(
            at: .init(row: images.count - 2, section: <your section index>),
            at: .centeredHorizontally,
            animated: false
        )
    }

    if point.x >= (groupWidth - section.interGroupSpacing) * CGFloat(images.count - 1) {
        self.collectionView.scrollToItem(
            at: .init(row: 1, section: <your section index>),
            at: .centeredHorizontally,
            animated: false
        )
    }
}

请注意,当您准备好显示数据时(例如,获得带有图像的响应),在重新加载数据之后,您必须立即调用:

collectionView.scrollToItem(at: .init(row: 1, section: <yout section index>), at: .centeredHorizontally, animated: false)
isHorizontalScrollingEnabled = true

isHorizontalScrollingEnabled(它的初始值显然等于false)用于防止在显示数据之前进行任何计算,而您实际上需要它,因为在您实际启动滚动之前,visibleItemsInvalidationHandler会被调用几次。

相关问题