Reputation: 11
I have a mosaic of cells with interleaved movement, but I have not achieved a toroidal effect so that the cells appear again.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
private var timer: Timer?
private var sections: Int = 5
private let cellSizes: [CGSize] = [
CGSize(width: 150, height: 200),
CGSize(width: 200, height: 150),
CGSize(width: 180, height: 180),
CGSize(width: 150, height: 200),
CGSize(width: 200, height: 150),
CGSize(width: 180, height: 180)
]
private var scrollDirections: [CGFloat] = []
private var sectionOffsets: [CGFloat] = []
override func viewDidLoad() {
super.viewDidLoad()
setupCollectionView()
setupScrollDirections()
startAutoScrolling()
}
private func setupCollectionView() {
collectionView.dataSource = self
collectionView.collectionViewLayout = createLayout()
collectionView.isPagingEnabled = false
collectionView.showsHorizontalScrollIndicator = false
collectionView.showsVerticalScrollIndicator = false
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
}
private func setupScrollDirections() {
for index in 0..<sections {
scrollDirections.append(index % 2 == 0 ? 1.0 : -1.0)
sectionOffsets.append(0.0)
}
}
private func createLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { sectionIndex, _ in
let itemSize = NSCollectionLayoutSize(
widthDimension: .absolute(self.cellSizes[sectionIndex % self.cellSizes.count].width),
heightDimension: .absolute(self.cellSizes[sectionIndex % self.cellSizes.count].height)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5)
let groupSize = NSCollectionLayoutSize(
widthDimension: .estimated(800),
heightDimension: .absolute(self.cellSizes[sectionIndex % self.cellSizes.count].height + 20)
)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
group.interItemSpacing = .fixed(10)
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
section.interGroupSpacing = 10
return section
}
return layout
}
private func startAutoScrolling() {
timer = Timer.scheduledTimer(timeInterval: 0.02, target: self, selector: #selector(performAutoScroll), userInfo: nil, repeats: true)
}
@objc private func performAutoScroll() {
for section in 0..<sections {
let direction = scrollDirections[section]
sectionOffsets[section] += 1.0 * direction
for cell in collectionView.visibleCells {
if let indexPath = collectionView.indexPath(for: cell), indexPath.section == section {
cell.transform = CGAffineTransform(translationX: sectionOffsets[section], y: 0)
let maxOffset = collectionView.contentSize.width
if abs(sectionOffsets[section]) > maxOffset {
sectionOffsets[section] = 0
}
}
}
}
}
deinit {
timer?.invalidate()
}
}
extension ViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return sections
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
cell.backgroundColor = randomColor()
cell.layer.cornerRadius = 8
return cell
}
private func randomColor() -> UIColor {
return UIColor(red: .random(in: 0...1),
green: .random(in: 0...1),
blue: .random(in: 0...1),
alpha: 1.0)
}
}
Upvotes: 0
Views: 27