導讀
拖拽排序是新聞類的App可以說是必有的互動設計,如今日頭條,網易新聞等。拖拽排序是一個互動體驗非常好的設計,簡單,方便。
今日頭條的拖拽排序介面
我實現的長按拖拽排序效果
實現方案
1.給CollectionViewCell新增一個長按手勢,通過協議把手勢傳遞到collectionView所在的控制器中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
- (void)awakeFromNib{ self.layer.cornerRadius = 3; self.layer.masksToBounds = YES; //給每個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]; } } |
2.開始長按時對cell進行截圖,並隱藏cell。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
- (void)longPress:(UILongPressGestureRecognizer *)longPress{ //記錄上一次手勢的位置 static CGPoint startPoint; //觸發長按手勢的cell MovingCell * cell = (MovingCell *)longPress.view; //開始長按 if (longPress.state == UIGestureRecognizerStateBegan) { [self shakeAllCell]; //獲取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]; } |
3、在手勢移動的時候,移動截圖檢視,用遍歷的方法求出截圖移動到哪個cell的位置,再呼叫系統的api交換這個cell和隱藏cell的位置,並且資料來源中的資料也需要調整順序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//手勢移動的時候 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; //設定截圖檢視位置 _snapshotView.center = CGPointApplyAffineTransform(_snapshotView.center, CGAffineTransformMakeTranslation(tranX, tranY)); startPoint = [longPress locationOfTouch:0 inView:_collectionView]; //計算截圖檢視和哪個cell相交 for (UICollectionViewCell *cell in [_collectionView visibleCells]) { //跳過隱藏的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)); //如果相交一半且兩個檢視Y的絕對值小於高度的一半就移動 if (space _indexPath.item) { for (NSUInteger i = _indexPath.item; i _nextIndexPath.item ; i --) { [self.array exchangeObjectAtIndex:i withObjectAtIndex:i - 1]; } } //移動 [_collectionView moveItemAtIndexPath:_indexPath toIndexPath:_nextIndexPath]; //設定移動後的起始indexPath _indexPath = _nextIndexPath; break; } } |
4.手勢停止時,移除截圖的view,顯示隱藏cell
1 2 3 4 5 6 |
//手勢停止時 }else if(longPress.state == UIGestureRecognizerStateEnded){ [self stopShake]; [_snapshotView removeFromSuperview]; _originalCell.hidden = NO; } |
其他
程式碼還可以進一步封裝,寫一個資料管理類dataTool,dataTool作為collectionView的資料來源,所有的資料來源方法都寫到dataTool類中。手勢的代理方法也在裡面實現,這樣控制器會簡潔很多,控制器就不需要關注拖拽排序的具體邏輯了。大家有空可以自己寫寫看,也許你們有更好的處理方案,可以評論交流一下。
github地址:https://github.com/HelloYeah/DraggingSort