UITableView交换单元格

时间:2014-05-07 21:51:11

标签: objective-c uitableview

在我的UITable视图中,我希望能够在将一个单元格拖到另一个单元格时切换两个单元格的位置。我已经完成了这项任务。唯一的问题是,当您尝试将一个拖过另一个时,后面的所有行都会向下移动以为新的行腾出空间。我不希望这样,当你拖动第一个单元格时,我希望单元格在视觉上保持静态。有什么想法吗?

谢谢, 米奇

2 个答案:

答案 0 :(得分:1)

我认为你可以用一些技巧来做到这一点,毕竟苹果公司是如何做很多动画的。

  1. 从UIViewController开始,以表格视图作为子视图

  2. 在主视图中添加一个平移手势识别器(您必须实现shouldRecognizeSimultaneouslyWithGestureRecognizer:并返回YES,这样它就可以使用表格视图自己的手势识别器)

  3. 当您开始拖动时,创建您开始拖动的单元格的快照视图,并将其添加为主视图的子视图。您可能还想在此时禁用表格视图的滚动。

  4. 使用平移手势识别器的translationInView属性拖动该快照视图

  5. 删除视图后,删除快照视图,并更新表格的数据源,以按照您使用移动创建的新订单显示数据。

  6. 我还没有尝试过所有这些(但我已经在其他项目中使用了它的一些元素),但我认为这应该会让你开始尝试实现的目标。 。还有一些细节可以肯定 - 你想在拖动细胞的地方看到什么?一片空白?拖动视图被删除后您想看到什么?

    编辑后:

    这是我到目前为止所做的,而且效果非常好。在故事板中,我有一个UITableViewController,它有两个基本类型的单元格原型。标识符为"空白"只是标签上没有文字。 tableviewController嵌入在导航控制器中,我在导航栏中添加了一个按钮,其初始标题为" Drag" - 此按钮连接到toggleDragging方法。

    @interface TableController ()
    @property (strong,nonatomic) NSMutableArray *theData;
    @property (strong,nonatomic)  UIPanGestureRecognizer *panner;
    @property (strong,nonatomic) UIView *cellSnapshotView;
    @property (strong,nonatomic) NSIndexPath *draggingCellIndexPath;
    @end
    
    @implementation TableController
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.panner = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveCellImage:)];
        [self.tableView addGestureRecognizer:self.panner];
        self.panner.enabled = NO;
        self.panner.delegate = self;
        self.draggingCellIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0];
        self.theData = [@[@"One",@"Two",@"Three",@"Four",@"Five",@"Six",@"Seven",@"Eight",@"Nine",@"Black",@"Brown",@"Red",@"Orange",@"Yellow",@"Green",@"Blue",@"Violet",@"Gray",@"White"] mutableCopy];
    }
    
    
    -(IBAction)toggleDragging:(UIBarButtonItem *)sender {
        if ([sender.title isEqualToString:@"Drag"]) {
            self.panner.enabled = YES;
            sender.title = @"Scroll";
        }else{
            self.panner.enabled = NO;
            sender.title = @"Drag";
            self.tableView.scrollEnabled = YES;
        }
    }
    
    
    
    -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        return YES;
    }
    
    
    
    -(IBAction)moveCellImage:(UIPanGestureRecognizer *)panner {
        if (! self.cellSnapshotView) {
            CGPoint loc = [panner locationInView:self.tableView];
            self.draggingCellIndexPath = [self.tableView indexPathForRowAtPoint:loc];
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.draggingCellIndexPath];
            self.cellSnapshotView = [cell snapshotViewAfterScreenUpdates:YES];
            self.cellSnapshotView.alpha = 0.8;
            self.cellSnapshotView.layer.borderColor = [UIColor redColor].CGColor;
            self.cellSnapshotView.layer.borderWidth = 1;
            self.cellSnapshotView.frame =  cell.frame;
            [self.tableView addSubview:self.cellSnapshotView];
            self.tableView.scrollEnabled = NO;
            [self.tableView reloadRowsAtIndexPaths:@[self.draggingCellIndexPath] withRowAnimation:UITableViewRowAnimationNone]; // replace the cell with a blank one until the drag is over
        }
    
        CGPoint translation = [panner translationInView:self.view];
        CGPoint cvCenter = self.cellSnapshotView.center;
        cvCenter.x += translation.x;
        cvCenter.y += translation.y;
        self.cellSnapshotView.center = cvCenter;
        [panner setTranslation:CGPointZero inView:self.view];
    
    
    
        if (panner.state == UIGestureRecognizerStateEnded) {
            UITableViewCell *droppedOnCell;
            CGRect largestRect = CGRectZero;
            for (UITableViewCell *cell in self.tableView.visibleCells) {
                CGRect intersection = CGRectIntersection(cell.frame, self.cellSnapshotView.frame);
                if (intersection.size.width * intersection.size.height >= largestRect.size.width * largestRect.size.height) {
                    largestRect = intersection;
                    droppedOnCell =  cell;
                }
            }
            NSIndexPath *droppedOnCellIndexPath = [self.tableView indexPathForCell:droppedOnCell];
            [UIView animateWithDuration:.2 animations:^{
                self.cellSnapshotView.center = droppedOnCell.center;
            } completion:^(BOOL finished) {
                [self.cellSnapshotView removeFromSuperview];
                self.cellSnapshotView = nil;
                NSIndexPath *savedDraggingCellIndexPath = self.draggingCellIndexPath;
                if (![self.draggingCellIndexPath isEqual:droppedOnCellIndexPath]) {
                    self.draggingCellIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0];
                    [self.theData exchangeObjectAtIndex:savedDraggingCellIndexPath.row withObjectAtIndex:droppedOnCellIndexPath.row];
                    [self.tableView reloadRowsAtIndexPaths:@[savedDraggingCellIndexPath, droppedOnCellIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                }else{
                    self.draggingCellIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0];
                    [self.tableView reloadRowsAtIndexPaths:@[savedDraggingCellIndexPath] withRowAnimation:UITableViewRowAnimationNone];
                }
            }];
        }
    }
    
    
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return self.theData.count;
    }
    
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
        if ([self.draggingCellIndexPath isEqual:indexPath]) {
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Blank" forIndexPath:indexPath];
            return cell;
        }
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
        cell.textLabel.text = self.theData[indexPath.row];
        return cell;
    }
    

答案 1 :(得分:0)

这可能会有所帮助,但您可以响应委托调用以实现此效果:

https://github.com/alfiehanssen/AMHEditableTableView

如果您有任何问题,请告诉我,