takeaway

Drag-and-drop sort is news App can be said to be a must interactive design, today’s Headlines, netease news and so on. Drag and drop sort is an interactive experience very good design, simple, convenient.

Github address: github.com/HelloYeah/D… Welcome Star, give people rose, hand has lingering fragrance.

Toutiao’s drag-and-sort interface

I implemented long drag sort effect

Implementation scheme

1. Add a pushdown gesture to the CollectionViewCell, and pass the gesture to the controller where the collectionView is located through the protocol.

- (void)awakeFromNib{ self.layer.cornerRadius = 3; self.layer.masksToBounds = YES; / / add a long press gesture to each cell UILongPressGestureRecognizer * longPress = [[UILongPressGestureRecognizer alloc] initWithTarget: self action:@selector(longPress:)]; longPress.delegate = self; [self addGestureRecognizer:longPress]; } - (void)longPress:(UILongPressGestureRecognizer *)longPress{ if (self.delegate && [self.delegate respondsToSelector:@selector(longPress:)]) { [self.delegate longPress:longPress]; }}Copy the code

2. Take snapshots of the cell for a long time and hide the cell.

- (void) longPress: (longPress UILongPressGestureRecognizer *) {/ / record last position of the gestures static CGPoint the startPoint; // Cell MovingCell * cell = (MovingCell *) longpress.view; / / long press the if (longPress. State = = UIGestureRecognizerStateBegan) {[self shakeAllCell]; / / get the screenshot of the cell _snapshotView = [cell snapshotViewAfterScreenUpdates: YES]; _snapshotView.center = cell.center; [_collectionView addSubview:_snapshotView]; _indexPath= [_collectionView indexPathForCell:cell]; _originalCell = cell; _originalCell.hidden = YES; startPoint = [longPress locationInView:_collectionView]; }Copy the code

3. When the gesture is moved, the screenshot view should be moved and the position of the cell to which the screenshot is moved should be figured out by traversal method. Then the API of the system should be called to exchange the position of the cell and the position of the hidden cell

/ / gestures move else if (longPress. State = = UIGestureRecognizerStateChanged) {CGFloat tranX = [longPress locationOfTouch: 0 inView:_collectionView].x - startPoint.x; CGFloat tranY = [longPress locationOfTouch:0 inView:_collectionView].y - startPoint.y; / / Settings screenshot _snapshotView view position. The center = CGPointApplyAffineTransform (_snapshotView center, CGAffineTransformMakeTranslation(tranX, tranY)); startPoint = [longPress locationOfTouch:0 inView:_collectionView]; For (UICollectionViewCell *cell in [_collectionView visibleCells]) {skip the hidden cell if ([_collectionView] indexPathForCell:cell] == _indexPath) { continue; } // CGFloat space = SQRTF (pow(_snapshotView.center.x - cell.center.x, 2) + powf(_snapshotView.center.y - cell.center.y, 2)); / / if the intersection of half and two views about half the absolute value of Y is less than the height of the mobile if (space < = _snapshotView. Bounds. Size. Width * 0.5 && (fabs (_snapshotView. Center. - Y Cell. Center. Y) < = _snapshotView. Bounds. Size. Height * 0.5)) {_nextIndexPath = [_collectionView indexPathForCell: cell]; if (_nextIndexPath.item > _indexPath.item) { for (NSUInteger i = _indexPath.item; i < _nextIndexPath.item ; i ++) { [self.array exchangeObjectAtIndex:i withObjectAtIndex:i + 1]; } }else{ for (NSUInteger i = _indexPath.item; i > _nextIndexPath.item ; i --) { [self.array exchangeObjectAtIndex:i withObjectAtIndex:i - 1]; } // move [_collectionView moveItemAtIndexPath:_indexPath toIndexPath:_nextIndexPath]; // Set the start indexPath _indexPath = _nextIndexPath; break; }}Copy the code

4. When the gesture stops, remove the view from the screenshot to display the hidden cell

Stop / / gestures} else if (longPress. State = = UIGestureRecognizerStateEnded) {[self stopShake]; [_snapshotView removeFromSuperview]; _originalCell.hidden = NO; }Copy the code
other

The code can be further encapsulated by writing a data management class called dataTool. The dataTool acts as the data source for the collectionView. All data source methods are written to the dataTool class. Gesture proxy method is also implemented in the inside, so the controller will be much simpler, the controller does not need to focus on the specific logic of drag and drop sort. You can write it yourself when you are free, maybe you have a better solution, you can comment and exchange.

Github address: github.com/HelloYeah/D…

prompt

If you’re starting with iOS9, you can use the Api, which is pretty easy to use

- (BOOL)collectionView (UICollectionView *)collectionView canMoveItemAtIndexPath (NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0); /** * drag from sourceIndexPath to destinationIndexPath to modify the data source in the proxy method. * exchangeObjectAtIndex:sourceIndexPath.item withObjectAtIndex: destinationIndexPath.item */ - (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath NS_AVAILABLE_IOS(9_0);Copy the code