首页 > 代码精文 > iOS > UI 进阶之拖拽排序的实现
2016
12-29

UI 进阶之拖拽排序的实现

导读

拖拽排序是新闻类的App可以说是必有的交互设计,如今日头条,网易新闻等。拖拽排序是一个交互体验非常好的设计,简单,方便。

今日头条的拖拽排序界面

UI 进阶之拖拽排序的实现

我实现的长按拖拽排序效果

UI 进阶之拖拽排序的实现

实现方案

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];
    }
}

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/

最后编辑:
作者:小企鹅
坚持+积累+学习
捐 赠如果您觉得这篇文章有用处,请支持作者!鼓励作者写出更好更多的文章!

留下一个回复