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 pathupdateInteractiveMovementTargetPosition(targetPosition: CGPoint)
which updates interactive movement target position during gestureendInteractiveMovement()
which ends interactive movement after you finish pan gesturecancelInteractiveMovement()
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!