Reputation: 1734
I wanted to make a circular collection view which scrolls like an spinner.
What I tried:
but collectionView doesn't scroll.
Link to the source code that I used: GitHub
Upvotes: 2
Views: 1395
Reputation: 5212
You need to use UIRotationGestureRecognizer:
When the user moves the fingers opposite each other in a circular motion, the underlying view should rotate in a corresponding direction and speed.
In order to do so, you could add the recognizer to the UICollectionView
:
let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotationRecognized(_:)))
collectionView?.addGestureRecognizer(rotationGesture)
Then recognize the direction and manually add or remove a cell:
@objc func rotationRecognized(_ sender: UIRotationGestureRecognizer) {
if sender.state == .began {
print("begin")
} else if sender.state == .changed {
print("changing")
let newRotation = sender.rotation
print(newRotation)
} else if sender.state == .ended {
print("end")
// Used 1 as an arbitrary minimum
if(sender.rotation > 1) {
self.collectionView?.performBatchUpdates({
self.numberOfCells += 1
self.collectionView?.insertItems(at: [IndexPath(item: 0, section: 0)])
})
}
if(sender.rotation < 1) {
self.collectionView?.performBatchUpdates({
self.numberOfCells -= 1
self.collectionView?.deleteItems(at: [IndexPath(item: 0, section: 0)])
})
}
}
}
Output:
EDIT
To simply rotate a view, you need to save its previous rotation and sum this with CGAffineTransform(rotationAngle:)
. As the example's collectionView is fullscreen, I needed to fix the size and center it on a UIVIewController
:
The code, then, would be like this:
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var numberOfCells = 10
var lastRotation: CGFloat = 0
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.collectionViewLayout = CircleLayout()
collectionView.delegate = self
collectionView.dataSource = self
let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotationRecognized(_:)))
collectionView.addGestureRecognizer(rotationGesture)
}
@objc func rotationRecognized(_ sender: UIRotationGestureRecognizer) {
if sender.state == .began {
print("begin")
sender.rotation = lastRotation
} else if sender.state == .changed {
print("changing")
let newRotation = sender.rotation + lastRotation
collectionView.transform = CGAffineTransform(rotationAngle: newRotation)
} else if sender.state == .ended {
print("end")
lastRotation = sender.rotation
}
}
// update collection view if size changes (e.g. rotate device)
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animateAlongsideTransition(in: view, animation: { _ in
self.collectionView?.performBatchUpdates(nil)
})
}
}
// MARK: UICollectionViewDataSource
extension ViewController {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numberOfCells
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CircleCell", for: indexPath)
return cell
}
}
And this is the output:
Upvotes: 4