UIPanGestureRecognizer是UIGestureRecognizer类的一个扩展类,其扩展类有UITapGestureRecognizer,UIPinchGestureRecognizer,UIRotationGestureRecognizer,UISwipeGestureRecognizer,UIPanGestureRecognizer,UILongPressGestureRecognizer。

借助这些类,可以实现UIView对象的一些操作如对象放大缩小,移动,旋转,滑动,轻击等。再也不用去重写UIView的touchBegin等方法来实现这些功能。

知识点:
UIGestureRecognizer是一个定义基本手势的抽象类,具体什么手势,在以下子类中包含:
    1、拍击UITapGestureRecognizer (任意次数的拍击)  
    2、向里或向外捏UIPinchGestureRecognizer (用于缩放)  
    3、摇动或者拖拽UIPanGestureRecognizer (拖动) 
    4、擦碰UISwipeGestureRecognizer (以任意方向)  
    5、旋转UIRotationGestureRecognizer (手指朝相反方向移动)  
    6、长按UILongPressGestureRecognizer (长按)

这些操作的目的都是用来修改UIView对象的frame,center,bounds属性,还有一个Transform属性。

我写了一个例子,在UIView和UITableView上分别添加UIPanGestureRecognizer,实现两个对象在手指按住对象于屏幕中拖动的效果。

声明一个UIPanGestureRecognizer对象,添加到UIView对象上去。UIView类有这样的方法用来动态添加和删除UIPanGestureRecognizer对象。

UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[testPanView addGestureRecognizer:panRecognizer];

UIView管理手势识别器的方法有:
– addGestureRecognizer:
– removeGestureRecognizer:
  gestureRecognizers  property
– gestureRecognizerShouldBegin:

我在viewDidAppear:方法中,动态添加视图和手势识别器。然后,实现识别器需要操作的两个方法,用来移动视图对象。
在这两个方法中最终的方法是这个 CGPoint translatedPoint = [recognizer translationInView:self.view];

每一次拖动操作状态,都会获取到translatedPoint,从开始到结束。它是一个绝对值,可以看着在”self.view“对应的坐标体系中,拖动的视图对象center的移动开始和结束的点差。
最简单的处理过程是这样:
    CGPoint translatedPoint = [recognizer translationInView:self.view];
    CGFloat x = recognizer.view.center.x + translatedPoint.x;
    CGFloat y = recognizer.view.center.y + translatedPoint.y;
    recognizer.view.center = CGPointMake(x, y);
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];

首先获取到移动点的值,然后算一下视图的center值,相加一下,就得到在self.view坐标体系中,视图该移动到那个center上,一次结束就清零一次。
因为拖动操作持续进行,所以,这个过程会持续执行。

稍微复杂点的处理过程,会捕获到拖动开始,移动,结束等几个状态下的translatedPoint的值。然后做一下逻辑处理,如视图不能溢出self.view的坐标系中,如在结束时会根据方向自动滑动到某个位置。可以在handlePan2:方法中找到这些逻辑的实现代码。

- (void)viewDidAppear:(BOOL)animated
{
    NSLog(@" viewDidAppear is at %@.", [NSDate date]);

UIImage *image = [UIImage imageNamed:@"5.jpg"];

testPanView = [[UIView alloc] initWithFrame:CGRectMake(18, 11, 100, 100)];

UIImageView *imageview = [[UIImageView alloc] initWithFrame:[testPanView frame]];
    [imageview setImage:image];
    [testPanView addSubview:imageview];

UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [panRecognizer setMinimumNumberOfTouches:1];
    [panRecognizer setMaximumNumberOfTouches:1];
    [panRecognizer setDelegate:self];
    [testPanView addGestureRecognizer:panRecognizer];

[self.view addSubview:testPanView];

testPanTableView = [[UITableView alloc] initWithFrame:CGRectMake(118, 121, 100, 100) style:UITableViewStylePlain];

UIPanGestureRecognizer *panRecognizer2 = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan2:)];
    [panRecognizer2 setMinimumNumberOfTouches:1];
    [panRecognizer2 setMaximumNumberOfTouches:1];
    [panRecognizer2 setDelegate:self];
    [testPanTableView addGestureRecognizer:panRecognizer2];

[self.view addSubview:testPanTableView];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    CGPoint translatedPoint = [recognizer translationInView:self.view];
    NSLog(@"gesture translatedPoint  is %@", NSStringFromCGPoint(translatedPoint));
    CGFloat x = recognizer.view.center.x + translatedPoint.x;
    CGFloat y = recognizer.view.center.y + translatedPoint.y;

recognizer.view.center = CGPointMake(x, y);

NSLog(@"pan gesture testPanView moving  is %@,%@", NSStringFromCGPoint(recognizer.view.center), NSStringFromCGRect(recognizer.view.frame));

[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}

- (void)handlePan2:(UIPanGestureRecognizer *)recognizer
{
    // NSLog(@"gesture translatedPoint  xxoo xxoo");
    CGPoint translatedPoint = [recognizer translationInView:self.view];

if ([(UIPanGestureRecognizer *)recognizer state] == UIGestureRecognizerStateBegan) {
        firstX = recognizer.view.center.x;
        firstY = recognizer.view.center.y;
        NSLog(@"self.view bounds is %@", NSStringFromCGRect(self.view.bounds));
        NSLog(@"pan gesture testPanView begin  is %@,%@", NSStringFromCGPoint([recognizer view].center), NSStringFromCGRect([recognizer view].frame));
    }

if ([(UIPanGestureRecognizer *)recognizer state] == UIGestureRecognizerStateChanged) {
        CGFloat x = firstX + translatedPoint.x;
        CGFloat y = firstX + translatedPoint.y;

if (x < recognizer.view.width / 2.0) {
            x = recognizer.view.width / 2.0;
        } else if (x + recognizer.view.width / 2.0 > self.view.width) {
            x = self.view.width - recognizer.view.width / 2.0;
        }

if (y < recognizer.view.height / 2.0) {
            y = recognizer.view.height / 2.0;
        } else if (y + recognizer.view.height / 2.0 > self.view.height) {
            y = self.view.height - recognizer.view.height / 2.0;
        }

NSLog(@"gesture translatedPoint moving  is %@", NSStringFromCGPoint(translatedPoint));

recognizer.view.center = CGPointMake(x, y);
    }

if (([(UIPanGestureRecognizer *)recognizer state] == UIGestureRecognizerStateEnded) || ([(UIPanGestureRecognizer *)recognizer state] == UIGestureRecognizerStateCancelled)) {
        CGFloat x = recognizer.view.center.x;
        CGFloat y = recognizer.view.center.y;

if (x > firstX) {
            x = self.view.width - recognizer.view.width / 2.0;
        } else {
            x = recognizer.view.width / 2.0;
        }

if (y > firstY) {
            y = self.view.height - recognizer.view.height / 2.0;
        } else {
            y = recognizer.view.height / 2.0;
        }

CGFloat velocityX = (0.2 *[recognizer velocityInView:self.view].x);

[UIView beginAnimations:nil context:NULL];

[UIView setAnimationDuration:ABS(velocityX * 0.00002 + 0.2)];

[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

recognizer.view.center = CGPointMake(x, y);

[UIView commitAnimations];

NSLog(@"gesture translatedPoint  end is %@", NSStringFromCGPoint(translatedPoint));

NSLog(@"pan gesture testPanView end  is %@,%@", NSStringFromCGPoint([recognizer view].center), NSStringFromCGRect([recognizer view].frame));
    }
}

(转)UIPanGestureRecognizer的更多相关文章

  1. 拖拽手势和清扫手势冲突时(UIPanGestureRecognizer和UISwipeGestureRecognizer冲突时)

    故事发生在这样的情境上:给整个控制器添加了一个拖拽手势,然后又在控制上的每个Cell上加了左滑清扫手势,然后问题来了:只有拖拽手势起作用,而左滑手势没有效果了,然后怎么解决这个问题呢!先上图: 当给整 ...

  2. 如何判断UIPanGestureRecognizer的拖动方向

    最近做一个项目,需要用到UIPanGestureRecognizer做一个侧滑菜单,需求是不能向右侧拖动(点击按钮右滑),但可以向左侧手势拖动收回:于是需要判断拖动的方向,百度了一下,网上大部分的答案 ...

  3. IOS开发之进阶篇第一章 - 姿势识别器UIPanGestureRecognizer

    今天讲一下姿势识别器,UIGestureRecognizer这个是抽象类 1.拍击UITapGestureRecognizer (任意次数的拍击) 2.向里或向外捏UIPinchGestureReco ...

  4. iOS开发 UIPanGestureRecognizer手势抽象类

    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@sel ...

  5. UIPanGestureRecognizer中translationInView的理解

    原因是在破船大牛的blog上面看到了一个demo #import <UIKit/UIKit.h> @interface ViewController : UIViewController ...

  6. UIPanGestureRecognizer

    http://blog.csdn.net/huifeidexin_1/article/details/8282035 UIGestureRecognizer是一个定义基本手势的抽象类,具体什么手势,在 ...

  7. uiscrollview上的 uipangesturerecognizer冲突

    最近在tableview里的cell imageview加了个 uipangesturerecognizer发现优先滚动imageview,往上拖的时候,tableView不响应滚动了,原来是tabl ...

  8. UIPanGestureRecognizer的使用

    UIGestureRecognizer是一个定义基本手势的抽象类,具体什么手势,在以下子类中包含: 1.拍击UITapGestureRecognizer (任意次数的拍击)      2.向里或向外捏 ...

  9. UIPanGestureRecognizer 拖动TableView改变其高度

    需求:项目中要求tableView的高度随着手拖动的位置而改变如下图: 关键代码如下: - (void)viewDidLoad{ panGestureRecognizer = [[UIPanGestu ...

  10. UIPanGestureRecognizer判断滑动的方向

    .h文件 CGFloat const gestureMinimumTranslation = 20.0 ; typedef enum : NSInteger { kCameraMoveDirectio ...

随机推荐

  1. [软件工程基础]2017.11.04 第八次 Scrum 会议

    具体事项 项目交接燃尽图 每人工作内容 成员 已完成的工作 计划完成的工作 工作中遇到的困难 游心 #10 搭建可用的开发测试环境:#9 阅读分析 PhyLab 后端代码与文档:#8 掌握 Larav ...

  2. 洛谷 P4092 [HEOI2016/TJOI2016]树 || bzoj4551

    https://www.lydsy.com/JudgeOnline/problem.php?id=4551 https://www.luogu.org/problemnew/show/P4092 这当 ...

  3. Java EE学习笔记(七)

    MyBatis的核心配置 1.MyBatis的核心对象 1).SqlSessionFactory是MyBatis框架中十分重要的对象,它是单个数据库映射关系经过编译后的内存镜像,其主要作用是创建Sql ...

  4. AmazeUI 保存浏览器数据 永久性

    //保存永久缓存数据function SaveAmuiStore(ItemName, ItemData){ if (window.localStorage) { var store = $.AMUI. ...

  5. 导入动态Web项目到Eclipse中遇到的问题

    问题一:创建动态网页项目时,项目报错而无文件报错 当时解决方法:直接右击项目->properties->project facets将jdk改为1.8版本即可 如图: 问题二:Tomcat ...

  6. jQuery.Deferred(jQuery1.5-2.1)源码剖析

    jQuery.Deferred作为1.5的新特性出现在jQuery上,而jQuery.ajax函数也做了相应的调整.因此我们能如下的使用xhr请求调用,并实现事件处理函数晚绑定. var promis ...

  7. CSS布局之-强大的负边距

    css中的负边距(negative margin)是布局中的一个常用技巧,只要运用得合理常常会有意想不到的效果.很多特殊的css布局方法都依赖于负边距,所以掌握它的用法对于前端的同学来说,那是必须的. ...

  8. 一次性删除数据库所有表和所有存储过程 SQL语句

    一次性删除数据库所有表和所有存储过程 SQL语句 今天转移数据库数据,需要把数据库原来的表和存储过程清空.删除所有的表:如果由于外键约束删除table失败,则先删除所有约束: --/第1步****** ...

  9. 从零开发分布式数据库中间件 二、构建MyBatis的读写分离数据库中间件

    在上一节 从零开发分布式数据库中间件 一.读写分离的数据库中间件 中,我们讲了如何通过ThreadLocal来指定每次访问的数据源,并通过jdbc的连接方式来切换数据源,那么这一节我们使用我们常用的数 ...

  10. 聊聊C语言和ABAP

    这个公众号之前的文章,分享的都是Jerry和SAP成都研究院的同事在工作中学到的一些知识和感受.而今天这篇文章,写作的由来是因为最近我又参与了SAP成都数字创新空间应聘者的面试,和一些朋友聊了一些关于 ...