With iOS 9 UICollectionView now has built-in drag and drop reorder. This is very easy to enable specially when using a UICollectionViewController.
However there is no animation showing that the move operation started or finished, and worse there is no delegate call or notification to be informed of move start/end.
So here is my UICollectionView subclass which adds:
- Wiggle animation while moving (taken from this library)
- isWiggling read-only property to check if collection view is currently moving a cell
- Notifications at start and end of move
Here is the code
// // WigglingCollectionView.swift // // Created by Ary Tebeka on 19/07/15. // Copyright © 2015 Ary Tebeka. All rights reserved. // import UIKit let WigglingCollectionViewStartedMovingNotification = "WigglingCollectionView.StartedMoving" let WigglingCollectionViewFinishedMovingNotification = "WigglingCollectionView.FinishedMoving" class WigglingCollectionView: UICollectionView { var isWiggling: Bool { return _isWiggling } private var _isWiggling = false override func beginInteractiveMovementForItemAtIndexPath(indexPath: NSIndexPath) -> Bool { startWiggle() NSNotificationCenter.defaultCenter().postNotificationName(WigglingCollectionViewStartedMovingNotification, object: self) return super.beginInteractiveMovementForItemAtIndexPath(indexPath) } override func endInteractiveMovement() { super.endInteractiveMovement() stopWiggle() NSNotificationCenter.defaultCenter().postNotificationName(WigglingCollectionViewFinishedMovingNotification, object: self) } // Wiggle code below from https://github.com/LiorNn/DragDropCollectionView private func startWiggle() { for cell in self.visibleCells() { addWiggleAnimationToCell(cell as UICollectionViewCell) } _isWiggling = true } private func stopWiggle() { for cell in self.visibleCells() { cell.layer.removeAllAnimations() } _isWiggling = false } private func addWiggleAnimationToCell(cell: UICollectionViewCell) { CATransaction.begin() CATransaction.setDisableActions(false) cell.layer.addAnimation(rotationAnimation(), forKey: "rotation") cell.layer.addAnimation(bounceAnimation(), forKey: "bounce") CATransaction.commit() } private func rotationAnimation() -> CAKeyframeAnimation { let animation = CAKeyframeAnimation(keyPath: "transform.rotation.z") let angle = CGFloat(0.04) let duration = NSTimeInterval(0.1) let variance = Double(0.025) animation.values = [angle, -angle] animation.autoreverses = true animation.duration = self.randomizeInterval(duration, withVariance: variance) animation.repeatCount = Float.infinity return animation } private func bounceAnimation() -> CAKeyframeAnimation { let animation = CAKeyframeAnimation(keyPath: "transform.translation.y") let bounce = CGFloat(3.0) let duration = NSTimeInterval(0.12) let variance = Double(0.025) animation.values = [bounce, -bounce] animation.autoreverses = true animation.duration = self.randomizeInterval(duration, withVariance: variance) animation.repeatCount = Float.infinity return animation } private func randomizeInterval(interval: NSTimeInterval, withVariance variance:Double) -> NSTimeInterval { let random = (Double(arc4random_uniform(1000)) - 500.0) / 500.0 return interval + variance * random; } }