美文网首页iOS收藏iOS技术专题iOS大咖
iOS开发:可拖动重排cell的tableView

iOS开发:可拖动重排cell的tableView

作者: Rusted | 来源:发表于2016-02-13 20:15 被阅读7225次

    本人iOS新手,借鉴前人经验封装了一个可拖动cell,重排cell的tableView,效果与iPhone自带天气应用中的tableView相似,可在多个section之间拖动重排,并且如果tableview内容大于屏幕,将cell拖至边缘时tableView会自动向上或向下滑动。

    GitHub下载地址
    效果如下:

    1.gif
    使用方法:
    • 必须实现的两个代理方法,在cell位置发生改变的时候同时更新外部数据源
    /**将外部数据源数组传入,以便在移动cell数据发生改变时进行修改重排*/
    - (NSArray *)originalArrayDataForTableView:(RTDragCellTableView *)tableView;
    /**将修改重排后的数组传入,以便外部更新数据源*/
    - (void)tableView:(RTDragCellTableView *)tableView newArrayDataForDataSource:(NSArray *)newArray;
    
    • 可选的三个代理方法,分别是cell的三种情况
    /**选中的cell准备好可以移动的时候*/
    - (void)tableView:(RTDragCellTableView *)tableView cellReadyToMoveAtIndexPath:(NSIndexPath *)indexPath;
    /**选中的cell正在移动,变换位置,手势尚未松开*/
    - (void)cellIsMovingInTableView:(RTDragCellTableView *)tableView;
    /**选中的cell完成移动,手势已松开*/
    - (void)cellDidEndMovingInTableView:(RTDragCellTableView *)tableView;
    
    基本思路:
    • 拖动效果通过添加一个长按手势和对选中的cell进行截图来实现。
    /**
     *  cell被长按手指选中,对其进行截图,原cell隐藏
     */
    - (void)cellSelectedAtIndexPath:(NSIndexPath *)indexPath{
        UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath];
        UIView *snapshot = [self customSnapshotFromView:cell];
        [self addSubview:snapshot];
        _snapshot = snapshot;
        cell.hidden = YES;
        CGPoint center = _snapshot.center;
        center.y = _fingerLocation.y;
        [UIView animateWithDuration:0.2 animations:^{
            _snapshot.transform = CGAffineTransformMakeScale(1.03, 1.03);
            _snapshot.alpha = 0.98;
            _snapshot.center = center;
        }];
    }
    
    • 在cell的截图被移动到其他indexPath范围时移动隐藏的那个cell,这时一定要先更新数据源再移动cell 位置,在跨section拖动的时候如果先移动cell再更新数据源会出现崩溃。
    - (void)cellRelocatedToNewIndexPath:(NSIndexPath *)indexPath{
        //更新数据源并返回给外部
        [self updateDataSource];
        //交换移动cell位置
        [self moveRowAtIndexPath:_originalIndexPath toIndexPath:indexPath];
        //更新cell的原始indexPath为当前indexPath
        _originalIndexPath = indexPath;
    }
    
    • 自动滚动效果的实现:在cell截图触碰顶部或底部时开启一个定时器,执行自动滚动方法
    - (void)startAutoScrollTimer{
        if (!_autoScrollTimer) {
            _autoScrollTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(startAutoScroll)];
            [_autoScrollTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
        }
    }
    

    通过计时器不断改变tableView的contentOffset达到自动滚动效果,并且可以调节滚动速度

    - (void)startAutoScroll{
        CGFloat pixelSpeed = 4;
        if (_autoScrollDirection == RTSnapshotMeetsEdgeTop) {//向下滚动
            if (self.contentOffset.y > 0) {//向下滚动最大范围限制
                [self setContentOffset:CGPointMake(0, self.contentOffset.y - pixelSpeed)];
                _snapshot.center = CGPointMake(_snapshot.center.x, _snapshot.center.y - pixelSpeed);
            }
        }else{                                               //向上滚动
            if (self.contentOffset.y + self.bounds.size.height < self.contentSize.height) {//向下滚动最大范围限制
                [self setContentOffset:CGPointMake(0, self.contentOffset.y + pixelSpeed)];
                _snapshot.center = CGPointMake(_snapshot.center.x, _snapshot.center.y + pixelSpeed);
            }
        }
    

    相关文章

      网友评论

      • 嫁给猿吧:代码是参考的,不是定制的,遇到问题自己分析代码解决,不要总伸手
      • 风语随风:系统cell交换怎么去掉左边的空白?
      • BohrIsLay:拖动到边缘,让cell自滚动,出现bug(本来选中一个cell,底部的cell隐藏了,在上边界或者下边界时,快速来回拖动,底部的cell没有隐藏,出现UI显示bug,数据还是对的),不知道有没有解决思路
      • 程序猿马国玺:你这个效果挺好的,请问如果部分cell不允许拖动怎么实现呢?
      • 锅锅中的鱼:空的数组无法拖入 怎么解决呀
      • 午马丶:你好你这个支持某几行不能拖动吗?
      • 1c7d043302da:带有区头的tableView,比如第一个section有2行,第二个section有3行,第三个seation有0行,第四个section有4行,现在把1,2,3任意一个section的cell移到3中,indexPath返回值为nil
        1c7d043302da:@锅锅中的鱼 我不让seation的cell个数为0,如果没有的话,就留一个空cell在那
        锅锅中的鱼:请问有解决方案吗
      • 一如初见丿:下拉到最下面 选中一个cell移动 tableView的contentOffset 会快速变动 是怎回事 我写的也有这个BUG 找不到解决方案 楼主可以看看吗 试个 两次三次 一定会重现
        一如初见丿:又试了下只在 iOS11 下有这个问题
      • YY_Lee:把你的初始化方法修改为- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style ,style传不支持UITableViewStyleGrouped拖动会崩溃reason: 'Invalid update: invalid number of rows in section 0.
      • 胖虎的胖zzZ:这么久了,不知道楼主还在不在,现在(iOS11)拖动tableview的最后几行cell的时候,tableview会不停刷新,导致位置乱跳,效果不好,不知道有没有什么好的解决办法。
      • SkyMing一C:如果 有section的标题会乱码
      • 9b23e56f13b4:您好,那个/**选中的cell完成移动,手势已松开*/怎么不执行
      • d922429c991f:楼主 有没有collection的demo
      • 波多多:楼主你好,按你demo上的写好之后 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath 这个代理方法不走了
      • Mars哥:UP, github上 delegate的几个方法好像没有写完,提醒一下~
      • 醉雨清风:楼主 你做gif用的什么工具,分享一下谢谢啦
      • KerwinC:学习了 谢谢分享
      • lsif的简书:demo中cell得选中方法didSelectRowAtIndexPath,不响应了是为什么?求解
        老子不去:你的解决了么,怎么解决的,我也是遇到了这个问题
      • Mzxer:学习了
      • f3b88f2da1d3:不在哇
      • f3b88f2da1d3:你能加我的qq吗????825307326
      • f3b88f2da1d3:如果我对我的cell的大小作出改变然后移动就会出现问题哦
      • 向日葵De视界:Mark, 一起学习
      • 凌虚若寒:/**选中的cell完成移动,手势已松开*/
        - (void)cellDidEndMovingInTableView:(RTDragCellTableView *)tableView;

        这个可选方法为什么没有效果呢?
        696cad56af9b:楼主能不能限制移动范围呢
        凌虚若寒:@Rusted 然而并不是,原因在于你的RTDragCellTableView.m实现文件中的- (void)didEndDraging方法里应该加上if ([self.delegate respondsToSelector:@selector(cellDidEndMovingInTableView:)]) {
        [self.delegate cellDidEndMovingInTableView:self];
        },你看呢?
        Rusted:@凌虚若寒 看看是不是没有设置代理
      • 一只小蝉儿:不错不错,项目正好用到 :smile: ,谢谢分享
      • 蓝猫淘气三千问:这个移动之后,再次点击会崩溃啊
        Rusted:@Wa4Ms :smile:不客气,大家一起学习交流
        蓝猫淘气三千问:@Rusted 没事了。我自己仿照写了一遍结果越界了 已经弄好了 谢谢博主分享😄
        Rusted:@Wa4Ms 你好,能说一下详细情况吗

      本文标题:iOS开发:可拖动重排cell的tableView

      本文链接:https://www.haomeiwen.com/subject/jcwukttx.html