前言
最近项目中需要拖动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
网友评论