UITableView 交换单元格 [英] UITableView swap cells

查看:34
本文介绍了UITableView 交换单元格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In my UITable view, i want to be able to switch the positions of two cells when you drag one on to the other. I have already completed this task. The only problem is that when you try to drag one over the other, all the rows that follow shift down to make room for the new one. I do not want this, I want the cells to essentially stay visually static when you are dragging the first cell around. Any ideas?

谢谢,米奇

推荐答案

我认为你可以通过一些技巧来做到这一点,毕竟 Apple 是如何制作大量动画的.

I think you can do this with some trickery, which is after all, how Apple does a lot of its animations.

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

  1. Start with a UIViewController with a table view as a subview

向主视图添加平移手势识别器(您必须实现 shouldRecognizeSimultaneouslyWithGestureRecognizer: 并返回 YES,因此它将与表视图自己的手势识别器一起使用)

Add a pan gesture recognizer to the main view (you'll have to implement shouldRecognizeSimultaneouslyWithGestureRecognizer: and return YES, so it will work with the table view's own gesture recognizers)

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

When you start to drag, create a snapshot view of the cell you started the drag over, and add it as a subview of the main view. You'll probably want to disable the table view's scrolling at this point also.

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

Drag that snapshot view using the pan gesture recognizer's translationInView property

当您删除视图时,删除快照视图,并更新表的数据源以按照您在移动时创建的新顺序显示数据.

When you drop the view, delete the snapshot view, and update the table's data source to show the data in the new order you created with the move.

我还没有尝试所有这些(但我已经在其他项目中使用了它的一些元素),但我认为这应该让您开始尝试实现的目标.还有一些细节需要确定——你想在你拖动单元格的地方看到什么?一片空白?当拖动的视图被放下时,你想看到什么?

I haven't tried all of this yet (but I've used some elements of it in other projects), but I think this should give you a start on what you're trying to achieve. There are some more details to work out for sure -- what do you want to see in the spot from where you dragged the cell? A blank space? What do you want to see when the dragged view is dropped?

编辑后:

这是我目前所拥有的,而且效果很好.在故事板中,我有一个 UITableViewController 有两个单元格原型,都是基本类型.标识符为Blank"的那个标签中没有文本.tableviewController 嵌入在导航控制器中,我在导航栏中添加了一个初始标题为Drag"的按钮——这个按钮连接到 toggleDragging 方法.

This is what I have so far, and it works pretty well. In the storyboard, I have a UITableViewController with two cell prototypes, both basic types. The one whose identifier is "Blank" just has no text in its label. The tableviewController is embedded in a navigation controller, and I've added a button to the navigation bar with the initial title of "Drag" -- this button is connected to the toggleDragging method.

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

这篇关于UITableView 交换单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆