uicollectionview
11 April 2023
UICollectionView实现一个无限循环列表
import UIKit
import SnapKit
class InfiniteScrollViewController: UIViewController {
private let cellIdentifier = "MyCell"
private let items = ["1", "2", "3", "4", "5"]
private var collectionView: UICollectionView!
private var currentIndex = 0
override func viewDidLoad() {
super.viewDidLoad()
// 创建UICollectionViewFlowLayout对象,并设置itemSize、minimumLineSpacing等属性
let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
flowLayout.minimumLineSpacing = 0
flowLayout.scrollDirection = .horizontal
// 创建UICollectionView对象,并注册cell、设置数据源和代理
collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
collectionView.backgroundColor = .white
collectionView.register(InfiniteUICollectionViewCell.self, forCellWithReuseIdentifier: cellIdentifier)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.showsHorizontalScrollIndicator = false
collectionView.isPagingEnabled = true
view.addSubview(collectionView)
// 设置collectionView水平方向上的约束
collectionView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
// 将collectionView的contentOffset调整到中间位置
let middleIndex = Int(items.count / 2)
let indexPath = IndexPath(item: middleIndex, section: 0)
collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false)
currentIndex = middleIndex
}
// 计算当前显示的索引
private func calculateCurrentIndex() -> Int {
let contentOffset = collectionView.contentOffset.x
let index = Int(round(contentOffset / UIScreen.main.bounds.width))
return index
}
}
extension InfiniteScrollViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// 数据源中的项数设置为items数组的两倍
return items.count * 2
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! InfiniteUICollectionViewCell
let itemIndex = indexPath.item % items.count
cell.update(itemIndex: itemIndex, text: items[itemIndex])
return cell
}
}
class InfiniteUICollectionViewCell: UICollectionViewCell {
var label: UILabel = {
return UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(label)
label.snp.makeConstraints { make in
make.center.equalToSuperview()
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(itemIndex: Int, text: String){
contentView.backgroundColor = (itemIndex % 2 == 0) ? .red : .orange
label.text = text
}
}
extension InfiniteScrollViewController: UICollectionViewDelegate {
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let index = calculateCurrentIndex()
if currentIndex != index {
currentIndex = index
let middleIndex = items.count
if index < middleIndex {
// 向前滚动一整页
let targetIndex = index + items.count
collectionView.scrollToItem(at: IndexPath(item: targetIndex, section: 0), at: .centeredHorizontally, animated: false)
} else if index > middleIndex {
// 向后滚动一整页
let targetIndex = index - items.count
collectionView.scrollToItem(at: IndexPath(item: targetIndex, section: 0), at: .centeredHorizontally, animated: false)
}
}
}
}
