UI 進階之拖拽排序的實現

cjdl8294 8年前發布 | 8K 次閱讀 iOS開發 移動開發

導讀

拖拽排序是新聞類的App可以說是必有的交互設計,如今日頭條,網易新聞等。拖拽排序是一個交互體驗非常好的設計,簡單,方便。

今日頭條的拖拽排序界面

我實現的長按拖拽排序效果

實現方案

1.給CollectionViewCell添加一個長按手勢,通過協議把手勢傳遞到collectionView所在的控制器中。

- (void)awakeFromNib{
    self.layer.cornerRadius = 3;
    self.layer.masksToBounds = YES;
    //給每個cell添加一個長按手勢
    UILongPressGestureRecognizer * longPress =[[UILongPressGestureRecognizeralloc]initWithTarget:selfaction:@selector(longPress:)];
    longPress.delegate = self;
    [self addGestureRecognizer:longPress];
}
 

  • (void)longPress:(UILongPressGestureRecognizer *)longPress{     if (self.delegate && [self.delegaterespondsToSelector:@selector(longPress:)]) {         [self.delegatelongPress:longPress];     } } </code></pre>

    2.開始長按時對cell進行截圖,并隱藏cell。

    - (void)longPress:(UILongPressGestureRecognizer *)longPress{
        //記錄上一次手勢的位置
        static CGPointstartPoint;
        //觸發長按手勢的cell
        MovingCell * cell = (MovingCell *)longPress.view;
        //開始長按
        if (longPress.state == UIGestureRecognizerStateBegan) {
            [self shakeAllCell];
            //獲取cell的截圖
            _snapshotView  = [cellsnapshotViewAfterScreenUpdates:YES];
            _snapshotView.center = cell.center;
            [_collectionViewaddSubview:_snapshotView];
            _indexPath= [_collectionViewindexPathForCell:cell];
            _originalCell = cell;
            _originalCell.hidden = YES;
            startPoint = [longPresslocationInView:_collectionView];
        }
    

    3、在手勢移動的時候,移動截圖視圖,用遍歷的方法求出截圖移動到哪個cell的位置,再調用系統的api交換這個cell和隱藏cell的位置,并且數據源中的數據也需要調整順序

        //手勢移動的時候
        else if (longPress.state == UIGestureRecognizerStateChanged){
        CGFloattranX = [longPresslocationOfTouch:0 inView:_collectionView].x - startPoint.x;
        CGFloattranY = [longPresslocationOfTouch:0 inView:_collectionView].y - startPoint.y;
        //設置截圖視圖位置
        _snapshotView.center = CGPointApplyAffineTransform(_snapshotView.center, CGAffineTransformMakeTranslation(tranX, tranY));
        startPoint = [longPresslocationOfTouch:0 inView:_collectionView];
        //計算截圖視圖和哪個cell相交
        for (UICollectionViewCell *cellin [_collectionViewvisibleCells]) {
            //跳過隱藏的cell
            if ([_collectionViewindexPathForCell:cell] == _indexPath) {
                continue;
            }
            //計算中心距
            CGFloatspace = 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];
                    }
                }
                //移動
                [_collectionViewmoveItemAtIndexPath:_indexPathtoIndexPath:_nextIndexPath];
                //設置移動后的起始indexPath
                _indexPath = _nextIndexPath;
                break;
            }
        }
    

    4.手勢停止時,移除截圖的view,顯示隱藏cell

    //手勢停止時
    }else if(longPress.state == UIGestureRecognizerStateEnded){
        [self stopShake];
        [_snapshotViewremoveFromSuperview];
        _originalCell.hidden = NO;
    }
    

    其他

    代碼還可以進一步封裝,寫一個數據管理類dataTool,dataTool作為collectionView的數據源,所有的數據源方法都寫到dataTool類中。手勢的代理方法也在里面實現,這樣控制器會簡潔很多,控制器就不需要關注拖拽排序的具體邏輯了。大家有空可以自己寫寫看,也許你們有更好的處理方案,可以評論交流一下。

     

    來自:http://ios.jobbole.com/90805/

     

 本文由用戶 cjdl8294 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!