iOS UITableView 长按移动Cell的位置

实现思路:

  1. 长按获取当前手指所在位置的indexPath
  2. 通过indexPath获取对应cell,并生成快照
  3. 移动。
    3.1. 快照跟随手指移动
    3.2. 当手指移动到其他cell的位置时,执行位置互换,和数据互换
  4. 放开手指,移除快照

实现步骤:

准备:(UITableView*)tableView,数据源(NSMutableArray*)lists

第一步:为tableView添加长按手势
1
2
3
UILongPressGestureRecognizer* longRec = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[_tableView addGestureRecognizer:longRec];

第二步:实现手势对应的操作。

UIGestureRecognizerStateBegan 时,选中cell。
通过手势在tableView的location,可以获取到tableView上对应的IndexPath,从而也能获取到对应的cell。

1
2
3
4
5
6
7
8
//UIGestureRecognizer 的实例方法,可获取手势在载体上的点坐标
- (CGPoint)locationInView:(nullable UIView*)view;

//UITableView 的实例方法,可获取屏幕上某个点下存在的indexPath
- (nullable NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point;

//UIView 的实例方法,可生成屏幕快照,要求iOS 7.0+
- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates;

UIGestureRecognizerStateChanged 时,移动cell。
通过手势在移动中,不断的回调,获取相应的位置,当手势移动到其他cell的位置时,就可以进行数据和视图的对调。

1
2
3
4
5
6
7
8
9
//NSMutableArray 的实例方法,可快速交换数组中两个对象的位置
- (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2;

//UITableView 的实例方法,可快速交换两个cell的位置,带动画
- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;

//UITableView 的实例方法,可快速交换两个section的位置,带动画
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;

UIGestureRecognizerStateEnded 时:放下cell,移除快照


完整的longPress:方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
- (void)longPress:(UILongPressGestureRecognizer*)sender{
UIGestureRecognizerState state = sender.state;
CGPoint location = [sender locationInView:_tableView];
switch (state) {
case UIGestureRecognizerStateBegan:{
NSLog(@"选中cell");
_selectIndexPath = [_tableView indexPathForRowAtPoint:location];
if (!_selectIndexPath) return;
UITableViewCell* cell = [_tableView cellForRowAtIndexPath:_selectIndexPath];
_snapShot = [self snapshotViewAfterScreenUpdates:cell];
_snapShot.frame = CGRectMake(0, location.y, _snapShot.bounds.size.width, _snapShot.bounds.size.height);
[self.view addSubview:_snapShot];
cell.contentView.hidden = YES;
}
break;
case UIGestureRecognizerStateChanged:{
NSLog(@"移动cell");
_snapShot.frame = CGRectMake(0, location.y, _snapShot.bounds.size.width, _snapShot.bounds.size.height);
NSIndexPath* changeIndexPath = [_tableView indexPathForRowAtPoint:location];
if (!_selectIndexPath || !changeIndexPath) return;
if (_selectIndexPath != changeIndexPath) {
NSLog(@"交换");
[self.lists exchangeObjectAtIndex:_selectIndexPath.row withObjectAtIndex:changeIndexPath.row];
//移动Section —— [self.tableView moveSection:0 toSection:0];
//移动row
[self.tableView moveRowAtIndexPath:_selectIndexPath toIndexPath:changeIndexPath];
UITableViewCell* selectCell = [_tableView cellForRowAtIndexPath:_selectIndexPath];
UITableViewCell* changeCell = [_tableView cellForRowAtIndexPath:changeIndexPath];
selectCell.contentView.hidden = NO;
changeCell.contentView.hidden = YES;
_selectIndexPath = changeIndexPath;
}
}
break;
case UIGestureRecognizerStateEnded:{
NSLog(@"放下cell");
[_snapShot removeFromSuperview];
_snapShot = nil;
if (!_selectIndexPath) return;
UITableViewCell* cell = [_tableView cellForRowAtIndexPath:_selectIndexPath];
cell.contentView.hidden = NO;
_selectIndexPath = nil;
}
break;
default:
break;
}
}

Demo

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

请我喝杯咖啡吧~

支付宝
微信