I’m a huge fan of
UICollectionView. It’s way more customizable than his older brother
UITableView. Nowadays I use collection view even more often than table view. With iOS 9 it supports easy reordering. Before it wasn’t possible out of the box, and to do so means painful work. Let’s have look at the API. You can find the accompanying Xcode project on GitHub.
The easiest way to add easy reordering is to use
UICollectionViewController. It now has a new property called
installsStandardGestureForInteractiveMovement which adds standard gestures to reorder cells. This property is
true by default, which means that there’s only one method we should to override to get things working.
1 2 3 4 5
The collection view infers that items can be moved because
moveItemAtIndexPath is overrired.
Things go complicated when we want to use a simple
UIViewController with collection view. We also need to implement
UICollectionViewDataSource methods mentioned above, but we need to rewrite
installsStandardGestureForInteractiveMovement. No worries, it’s also easily supported.
UILongPressGestureRecognizer is a continuous gesture recognizer and fully supports panning.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
We stored selected index path obtained in long press gesture handler and depending on wether it has any value we allow to pan gesture to kick in. Then, we call some new collection view methods accordingly to the gesture state:
beginInteractiveMovementForItemAtIndexPath(indexPath: NSIndexPath)which starts interactive movement for cell at specific index path
updateInteractiveMovementTargetPosition(targetPosition: CGPoint)which updates interactive movement target position during gesture
endInteractiveMovement()which ends interactive movement after you finish pan gesture
cancelInteractiveMovement()which cancels interactive movement
And this makes handling pan gesture obvious.
The behavior is the same as with standard
UICollectionViewController. Really cool, but what makes it even cooler is that we can apply reordering to collection view with our custom collection view layout. Check interactive movement with simple waterfall layout.
Uhm, looks cool, but what if we don’t want to change cell size during movement? Selected cell size during interactive movement should remain the same. This is possible.
UICollectionViewLayout also gets additional methods to handle reordering.
1 2 3 4 5 6 7 8
The former is called during the cells interactive movement with target and previous cell’s indexPaths. The next one is similar, but it’s called just after interactive movement ends. With this knowledge we can achieve our requirement using one little trick.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Solution is straightforward. Grab previous and target index paths of currently moving cell. Then call
UICollectionViewDataSource method to move this items around.
Without a doubt, a collection view reordering is a fantastic addition. UIKit engineers made awesome job! :)
P.S: I would like to thanks Douglas Hill for hinting out some improvements in our code. Thanks Douglas, keep up the good work!