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;
}
}