Mohammad Reza Koohkan
Mohammad Reza Koohkan

Reputation: 1734

How to scroll Circular CollectionView

I wanted to make a circular collection view which scrolls like an spinner.

What I tried:

The action that I wanted

but collectionView doesn't scroll.

Link to the source code that I used: GitHub

Upvotes: 2

Views: 1395

Answers (1)

alxlives
alxlives

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:

Example gif

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:

enter image description here

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:

enter image description here

Upvotes: 4

Related Questions