UITableViewCell单Section及多Section的Cell手势拖动

前言

最近项目中需要拖动UITableViewCell进行排序,基于系统的方法只能进入编辑模式触发,且没有Section间的控制方法,UI也有局限性,所以参考网上做法实现如下效果:


image.png

以实现不同的Section间单独处理。

首先

cell的操作图片上添加长按手势,根据state的值进行操作

- (void)dragCell:(UITableViewCell *)cell recognizer:(UILongPressGestureRecognizer *)longPress {
    UIGestureRecognizerState state = longPress.state;
    switch (state) {
        case UIGestureRecognizerStateBegan: {
            NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
            if (indexPath) {
                self.sourceIndexPath = indexPath;
                self.snapshot = [self customSnapshoFromView:cell];
                __block CGPoint center = cell.center;
                self.snapshot.center = center;
                self.snapshot.alpha = 0.0;
                [self.tableView addSubview:self.snapshot];

                [UIView animateWithDuration:0.25 animations:^{
                    self.snapshot.center = center;
                    self.snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05);
                    self.snapshot.alpha = 0.98;
                    cell.alpha = 0.0f;
                } completion:^(BOOL finished) {
                    cell.hidden = YES;
                }];
            }

            break;
        }
            
        case UIGestureRecognizerStateChanged: {
            CGPoint location = [longPress locationOfTouch:0 inView:self.tableView];
            CGPoint center = self.snapshot.center;
            center.y = location.y;
            self.snapshot.center = center;
            NSIndexPath *changedIndexPath = [self.tableView indexPathForRowAtPoint:location];

            // 是否位置变动
            if (changedIndexPath && ![changedIndexPath isEqual:self.sourceIndexPath]) {
                if (changedIndexPath.section != self.sourceIndexPath.section) {
                    return;
                }
                // 要拖动的数据
                NSArray *sectionArry = self.getAdapterArry[self.sourceIndexPath.section];
                // 移动数据交换
                NSMutableArray *sourceSectionArry = sectionArry.mutableCopy;
                [sourceSectionArry exchangeObjectAtIndex:changedIndexPath.row withObjectAtIndex:self.sourceIndexPath.row];
                // 更新数据源
                [self.getAdapterArry replaceObjectAtIndex:self.sourceIndexPath.section withObject:sourceSectionArry];
                [[YSCommonDataManager shareManager] addtoKLineIndexStyleSet:self.getAdapterArry];
                
                [self.tableView moveRowAtIndexPath:self.sourceIndexPath toIndexPath:changedIndexPath];
                self.sourceIndexPath = changedIndexPath;
            }
            
            break;
        }
        // 最后就是默认(拖动完成或者未拖动)
        default: {
            // Clean up.
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.sourceIndexPath];
            
            [UIView animateWithDuration:0.25 animations:^{
                self.snapshot.center = cell.center;
                self.snapshot.transform = CGAffineTransformIdentity;
                self.snapshot.alpha = 0.0;
                cell.alpha = 1.0f;
            } completion:^(BOOL finished) {
                cell.hidden = NO;
                [self.snapshot removeFromSuperview];
                self.snapshot = nil;
            }];
            self.sourceIndexPath = nil;
            
            break;
        }
    }
}

接着

为了能实现悬浮的效果,需要创建一个快照视图。
@property (nonatomic, strong) UIView *snapshot;

- (UIView *)customSnapshoFromView:(UIView *)inputView {
    UIView *snapshot = nil;
    snapshot = [inputView snapshotViewAfterScreenUpdates:YES];
    snapshot.layer.masksToBounds = NO;
    snapshot.layer.cornerRadius = 0.0;
    snapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0);
    snapshot.layer.shadowRadius = 5.0;
    snapshot.layer.shadowOpacity = 0.4;
    
    return snapshot;
}
  • UIGestureRecognizerStateBegan时,获取被移动cell的起始位置sourceIndexPath,将snapshot快照视图加入到tableView上,隐藏原来的cell
  • UIGestureRecognizerStateChanged时,获取到按压手势的偏移位置,调整snapshot的位置,得到快照被拖移到的新位置changedIndexPath,后根据
    // 是否位置变动
    if (changedIndexPath && ![changedIndexPath isEqual:self.sourceIndexPath]) { if (changedIndexPath.section != self.sourceIndexPath.section) { return; } }
    来隔断不同section间的拖动。以及进行数据源交换,cell交换,更新sourceIndexPath等操作。
  • 最后在default状态,根据最新的sourceIndexPath来完成拖动完成或者失败的动画效果。

至此

完成了单Section及多Section的Cell手势拖动。

参考文章和源码:
iOS UITableView可以拖动排序的Cell

你可能感兴趣的:(UITableViewCell单Section及多Section的Cell手势拖动)