起因

  • 最近在做一个项目,要对UITableViewCell进行拖动蹂躏,具体效果如下:

  • 本来打算用UIRespon这几个方法来做,最后发现在UITableViewController中这几个方法不会被响应,具体原因详情见Stack Overflow,于是就选择了使用长按手势来实现,好吧,废话不多少了,直接上料子。

经过

思考

让我们来理清思路,大致分为这几步

  • 首先创建手势并添加,响应手势定义的方法。
  • 接下根据长按手势的三种状态,分别是起始,改变,结束,在这三种不同状态下我们可以做一些事情。我的思路是在长按手势开始时为cell创建一个快照(可以理解为把cell截成一张图),然后把cell隐藏,之后我们移动的过程中对cell的快照进行操作,等到移动完毕,也就是长按手势结束,显示cell,然后就可以把快照无情的抛弃了。

开动

#pragma mark 设置长按拖动cell
- (void)setLongPressDrag
{UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognized:)];[self.tableView addGestureRecognizer:longPress];
}
这个就是创建并添加长按手势,很简单,不再赘述。
#pragma mark 创建cell的快照
- (UIView *)customSnapshoFromView:(UIView *)inputView {// 用cell的图层生成UIImage,方便一会显示UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, NO, 0);[inputView.layer renderInContext:UIGraphicsGetCurrentContext()];UIImage *image = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();// 自定义这个快照的样子(下面的一些参数可以自己随意设置)UIView *snapshot = [[UIImageView alloc] initWithImage:image];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;
}
为cell创建一个快照,等会就可以用上它了。
pragma mark 长按手势方法
- (void)longPressGestureRecognized:(id)sender {UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender;UIGestureRecognizerState state = longPress.state;CGPoint location = [longPress locationInView:self.tableView];NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];static UIView       *snapshot = nil;static NSIndexPath  *sourceIndexPath = nil;switch (state) {// 已经开始按下case UIGestureRecognizerStateBegan: {// 判断是不是按在了cell上面if (indexPath) {sourceIndexPath = indexPath;UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];// 为拖动的cell添加一个快照snapshot = [self customSnapshoFromView:cell];// 添加快照至tableView中__block CGPoint center = cell.center;snapshot.center = center;snapshot.alpha = 0.0;[self.tableView addSubview:snapshot];// 按下的瞬间执行动画[UIView animateWithDuration:0.25 animations:^{center.y = location.y;snapshot.center = center;snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05);snapshot.alpha = 0.98;cell.alpha = 0.0;} completion:^(BOOL finished) {cell.hidden = YES;}];}break;}// 移动过程中case UIGestureRecognizerStateChanged: {// 这里保持数组里面只有最新的两次触摸点的坐标[self.touchPoints addObject:[NSValue valueWithCGPoint:location]];if (self.touchPoints.count > 2) {[self.touchPoints removeObjectAtIndex:0];}CGPoint center = snapshot.center;// 快照随触摸点y值移动(当然也可以根据触摸点的y轴移动量来移动)center.y = location.y;// 快照随触摸点x值改变量移动CGPoint Ppoint = [[self.touchPoints firstObject] CGPointValue];CGPoint Npoint = [[self.touchPoints lastObject] CGPointValue];CGFloat moveX = Npoint.x - Ppoint.x;center.x += moveX;snapshot.center = center;NSLog(@"%@---%f----%@", self.touchPoints, moveX, NSStringFromCGPoint(center));NSLog(@"%@", NSStringFromCGRect(snapshot.frame));// 是否移动了if (indexPath && ![indexPath isEqual:sourceIndexPath]) {// 更新数组中的内容[self.dataArray exchangeObjectAtIndex:indexPath.row withObjectAtIndex:sourceIndexPath.row];// 把cell移动至指定行[self.tableView moveRowAtIndexPath:sourceIndexPath toIndexPath:indexPath];// 存储改变后indexPath的值,以便下次比较sourceIndexPath = indexPath;}break;}// 长按手势取消状态default: {// 清除操作// 清空数组,非常重要,不然会发生坐标突变![self.touchPoints removeAllObjects];UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:sourceIndexPath];cell.hidden = NO;cell.alpha = 0.0;// 将快照恢复到初始状态[UIView animateWithDuration:0.25 animations:^{snapshot.center = cell.center;snapshot.transform = CGAffineTransformIdentity;snapshot.alpha = 0.0;cell.alpha = 1.0;} completion:^(BOOL finished) {sourceIndexPath = nil;[snapshot removeFromSuperview];snapshot = nil;}];break;}}}

长按手势的响应方法,这里创建cell快照,并对快照进行坐标的改变。需要注意的是在长按手势结束的时候一定要把存放触摸点坐标的数组清空,不然下次再继续点击的时候,如果点击的位置距离上次较远,cell快照会突然大幅度移动。

结语

感谢那位外国网友提供的一些思路及技巧,大家如果发现有任何问题,请告知我和bug有个约会,互相交流,寻求技术的巅峰。

  • 如有转载,请注明出处。

iOS自定义长按手势,随意拖动Cell相关推荐

  1. [IOS]自定义长触屏事件

    写一个Demo来自定义一个长触屏事件,自定义长按手势. 实现步骤: 1.创建一个自定义手势类,命名为LongPressGestureRecognizer,在创建的时候继承UIGestureRecogn ...

  2. iOS 利用长按手势移动 Table View Cells

    本文译自:Cookbook: Moving Table View Cells with a Long Press Gesture 目录: 你需要什么? 如何做? 如何将其利用至UICollection ...

  3. IOS 自定义 滑动返回 手势

    /** 只需要在你自定义的导航控制器中,改成如下代码即可,自定义手势返回 */ #define KEY_WINDOW [[UIApplication sharedApplication] keyWin ...

  4. IOS 定义手势监听器详解,利用 UIGestureRecognizer 进行捏合、旋转、平移、点击、长按手势事件响应

    IOS中我们可以通过UITouch进行触摸事件监听,但是UITouch实现捏合.旋转.长按等手势事件监听非常麻烦.IOS中提供 UIGestureRecognizer 的子类帮我们简洁等实现捏合.旋转 ...

  5. ios cell点击对勾_带图像和对勾的iOS自定义TableView

    ios cell点击对勾 In this tutorial, we'll be developing an iOS Application that contains a custom TableVi ...

  6. iOS——自定义cell

    iOS--自定义cell 在写自定义cell怎么实现之前,先来看一下自定义cell的作用和用法,这一点远远比怎么实现有用的多,在进行了两天的网易云仿写后,才发现自己对自定义cell的理解完全是错的,按 ...

  7. iOS学习—iOS长按手势事件

    iOS手势状态: typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {UIGestureRecognizerStatePossible, // ...

  8. iOS手势全埋点:轻拍手势、长按手势、捏合手势、旋转手势、轻扫手势、平移手势、屏幕边缘平移手势

    文章目录 前言 I.手势全埋点方案 1.1 轻拍手势全埋点 1.2 长按手势全埋点 II .右划返回的事件与scrollView滚动事件冲突的解决方案 see also 前言 由于UIGestureR ...

  9. iOS 全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突

    七夕节福利 效果预览 一.前期准备 有一个支持全屏侧滑返回的视图控制器ViewController,ViewController.view上有一个UIScrollView,UIScrollView上有 ...

最新文章

  1. 机械硬盘 mysql调优_【MYSQL】使用RAID增加传统机器硬盘的性能
  2. 比较二进制_浮点数比较的精度问题
  3. cocos2dx游戏开发简单入门视频教程 (cocos2d-x)- 第5天
  4. 设计模式之Flyweight模式(笔记)
  5. JointJS绘制流程图
  6. java语言的演化——读JavaOne ppt笔记
  7. CocurrentHashMap和Hashtable的区别
  8. 190522每日一句
  9. U盘文件消失没有被隐藏却占内存的几种解决方案
  10. excel 数组函数入门讲座
  11. mq消息队列到底是什么
  12. NVIDIA GPU Compute Capability
  13. 日本語を勉強するの日記(四)
  14. FORECAST函数预算产品的使用寿命测试值
  15. python里float什么意思_Python中的float是什么意思,小白求答?
  16. 基于PaddleOCR银行卡识别实现(一)
  17. 正则表达式-匹配A和B之间字符串
  18. 数据挖掘导论(Pang-Ning Tan)习题记录
  19. iOS本地数据存储安全
  20. adb 禁用手机系统的更新

热门文章

  1. VS2008简体中文正式版迅雷高速下载 Visual Studio 2008 Team Suite
  2. BIOS和DOS中断大全
  3. 室外排水设计规范_房屋建筑工程现行规范标准目录汇编(2020版)—给排水—图集篇...
  4. 打包报错:CSS minification error: Lexical error on line 1: Unrecognized text.
  5. r7 5700g对比5800x选哪个
  6. AI微信小程序源码下载照片AI转换动漫照片源码安装简单无需服务器域名
  7. 【智慧气象】道路气象监测系统
  8. iOS---The maximum number of apps for free development profiles has been reached.
  9. 考虑迂曲度τ的时候渗透率与平均空隙半径的关系公式
  10. java前端的日期插件_几个前端时间插件总结