天天看点

iOS手势UIGestureRecognizer

原文地址:http://www.cocoachina.com/newbie/basic/2012/0604/4322.html

http://www.cocoachina.com/newbie/basic/2013/0501/6108.html

UIKit中包含了UIGestureRecognizer类,用于检测发生在设备中的手势。UIGestureRecognizer是一个抽象类,定义了所有手势的基本行为,它有下面一些子类用于处理具体的手势:  

  1、拍击UITapGestureRecognizer (任意次数的拍击)   

  2、向里或向外捏UIPinchGestureRecognizer (用于缩放)   

  3、摇动或者拖拽UIPanGestureRecognizer   (拖移,慢速移动)

  4、擦碰UISwipeGestureRecognizer (以任意方向)   (滑动,快速移动)

  5、旋转UIRotationGestureRecognizer (手指朝相反方向移动)   

  6、长按UILongPressGestureRecognizer  

UIGestureRecognizer的继承关系如下:

iOS手势UIGestureRecognizer

对于不同类型的手势识别器,具有不同的配置属性。比如UITapGestureRecognizer,可以配置拍击次数。界面接收到手势之后,可以发送一个消息,用于处理响应手势动作后的任务。当然,不同的手势识别器,发送的消息方法也会有所不同。下面列举几个具体示例代码:  

1、一个手指,拍击两次手势 

// 创建一个手势识别器 
 
UITapGestureRecognizer *oneFingerTwoTaps = 
 
  [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(oneFingerTwoTaps)] autorelease]; 
 
// Set required taps and number of touches 
 
[oneFingerTwoTaps setNumberOfTapsRequired:2]; 
 
[oneFingerTwoTaps setNumberOfTouchesRequired:1]; 
 
// Add the gesture to the view 
 
[[self view] addGestureRecognizer:oneFingerTwoTaps]; 
 
//消息方法oneFingerTwoTaps 
 
- (void)oneFingerTwoTaps 
 
{ 
 
  NSLog(@"Action: One finger, two taps"); 
 
} 
           

2、两个手指,拍击两次手势 

UITapGestureRecognizer *twoFingersTwoTaps = 
 
      [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersTwoTaps)] autorelease]; 
 
    [twoFingersTwoTaps setNumberOfTapsRequired:2]; 
 
    [twoFingersTwoTaps setNumberOfTouchesRequired:2]; 
 
    [[self view] addGestureRecognizer:twoFingersTwoTaps]; 
 
//消息方法twoFingersTwoTaps 
 
    - (void)twoFingersTwoTaps { 
 
      NSLog(@"Action: Two fingers, two taps"); 
 
    } 
           

3、一个手指向上、向下滑动手势 

// 向上擦碰 
 
    UISwipeGestureRecognizer *oneFingerSwipeUp = 
 
      [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(oneFingerSwipeUp:)] autorelease]; 
 
    [oneFingerSwipeUp setDirection:UISwipeGestureRecognizerDirectionUp]; 
 
    [[self view] addGestureRecognizer:oneFingerSwipeUp]; 
 
      
 
    - (void)oneFingerSwipeUp:(UISwipeGestureRecognizer *)recognizer 
 
    { 
 
      CGPoint point = [recognizer locationInView:[self view]]; 
 
      NSLog(@"Swipe up - start location: %f,%f", point.x, point.y); 
 
    } 
 
    // 向下擦碰 
 
    UISwipeGestureRecognizer *oneFingerSwipeDown = 
 
      [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(oneFingerSwipeDown:)] autorelease]; 
 
    [oneFingerSwipeDown setDirection:UISwipeGestureRecognizerDirectionDown]; 
 
    [[self view] addGestureRecognizer:oneFingerSwipeDown]; 
 
      
 
    - (void)oneFingerSwipeDown:(UISwipeGestureRecognizer *)recognizer 
 
    { 
 
      CGPoint point = [recognizer locationInView:[self view]]; 
 
      NSLog(@"Swipe down - start location: %f,%f", point.x, point.y); 
 
    } 
           

4、旋转手势 

UIRotationGestureRecognizer *twoFingersRotate = 
 
  [[[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersRotate:)] autorelease]; 
 
[[self view] addGestureRecognizer:twoFingersRotate]; 
 
 
 
- (void)twoFingersRotate:(UIRotationGestureRecognizer *)recognizer 
 
{ 
 
  // Convert the radian value to show the degree of rotation 
 
  NSLog(@"Rotation in degrees since last change: %f", [recognizer rotation] * (180 / M_PI)); 
 
} 
           
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    /******添加Label组件 start******/
    self.helloWorldLabel = [[UILabel alloc] initWithFrame:CGRectZero];
    self.helloWorldLabel.text = @"Hello, World!";
    self.helloWorldLabel.font = [UIFont systemFontOfSize:16.0f];
    [self.helloWorldLabel sizeToFit];
    //居中
    self.helloWorldLabel.center = self.view.center;
    [self.view addSubview:self.helloWorldLabel];
    /******添加Label组件 end******/
    //UIRotationGestureRecognizer 手势识别器,这个类能用来监听和捕获旋转的手势,添加一个旋转的手势识别器,这样用户就可以顺利的使 用手势来调整图片的位置。
    self.rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotations:)];
    //添加手势
    [self.view addGestureRecognizer:self.rotationGestureRecognizer];
    
}

- (void) handleRotations:(UIRotationGestureRecognizer *)paramSender{
    if (self.helloWorldLabel == nil){ return;
    }
    //利用 CGAffineTransformMakeRotation 这 个方法来进行一个旋转手势的事件传递.将前一个旋转的弧度和当前的旋转弧度相加
    //rotationAngleInRadians 这个对象就是我们在旋转的时候需要为我们的标签对象设置的一个位置对象信息,当我们每一次旋转的时 候我们都会把一个新的位置值保存在这个对象里面,达到一个旋转的效果。
    self.helloWorldLabel.transform = CGAffineTransformMakeRotation(self.rotationAngleInRadians + paramSender.rotation);
    //手势结束时候,调整视图位置
    if (paramSender.state == UIGestureRecognizerStateEnded){
        self.rotationAngleInRadians += paramSender.rotation;
    }
}
           

5、拖拽手势

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    /* Let's first create a label */
    CGRect labelFrame = CGRectMake(0.0f, /* X */
                                   0.0f, /* Y */
                                   150.0f, /* 宽 */
                                   100.0f); /* 高 */
    self.helloWorldLabel = [[UILabel alloc] initWithFrame:labelFrame];
    self.helloWorldLabel.text = @"Hello World";
    self.helloWorldLabel.backgroundColor = [UIColor blackColor];
    self.helloWorldLabel.textColor = [UIColor whiteColor];
    self.helloWorldLabel.textAlignment = NSTextAlignmentCenter;
    //确保label可以互动的属性,以便可以激活其方法
    self.helloWorldLabel.userInteractionEnabled = YES;
    [self.view addSubview:self.helloWorldLabel];
    //创建拖拽手势
    self.panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self
                                                                        action:@selector(handlePanGestures:)];
    //无论最大还是最小都只允许一个手指
    self.panGestureRecognizer.minimumNumberOfTouches = 1;
    self.panGestureRecognizer.maximumNumberOfTouches = 1;
    [self.helloWorldLabel addGestureRecognizer:self.panGestureRecognizer];
}

- (void) handlePanGestures:(UIPanGestureRecognizer*)paramSender{
    if (paramSender.state != UIGestureRecognizerStateEnded && paramSender.state != UIGestureRecognizerStateFailed){
        //通过使用 locationInView 这个方法,来获取到手势的坐标
        CGPoint location = [paramSender locationInView:paramSender.view.superview];
        paramSender.view.center = location;
    }
}
           

6、缩放手势 

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    CGRect labelRect = CGRectMake(0.0f, 0.0f, 200.0f, 200.0f);
    self.myBlackLabel = [[UILabel alloc] initWithFrame:labelRect];
    self.myBlackLabel.center = self.view.center;
    self.myBlackLabel.backgroundColor = [UIColor blackColor];
    /* 使UIPinchGestureRecognizer聚拉的手势的放大缩小功能生效 */
    self.myBlackLabel.userInteractionEnabled = YES;
    [self.view addSubview:self.myBlackLabel];
    self.pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self
                                                                            action:@selector(handlePinches:)];
    [self.myBlackLabel addGestureRecognizer:self.pinchGestureRecognizer];
}

- (void) handlePinches:(UIPinchGestureRecognizer*)paramSender{
    //UIPinchGestureRecognizer其中有两个比较重要的变量 scale 和 velocity,前者是一个比例范围,后者是一个变化速率的,也就是说每次变化的一个像素点。
    if (paramSender.state == UIGestureRecognizerStateEnded){
        self.currentScale = paramSender.scale;
    } else if (paramSender.state == UIGestureRecognizerStateBegan && self.currentScale != 0.0f){
        paramSender.scale = self.currentScale;
    }
    if (paramSender.scale != NAN && paramSender.scale != 0.0){
        paramSender.view.transform = CGAffineTransformMakeScale(paramSender.scale, paramSender.scale);
    }  
}
           

7、长按手势

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.dummyButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.dummyButton.frame = CGRectMake(0.0f,0.0f, 100.0f, 37.0f);
    self.dummyButton.center = self.view.center;
    [self.dummyButton setTitle:@"注意我的位置" forState:UIControlStateNormal];
    [self.view addSubview:self.dummyButton];
    /*第一次创建手势识别器*/
    self.longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(handleLongPressGestures:)];
    /* numberOfTouchesRequired这个属性保存了有多少个手指点击了屏幕,因此你要确保你每次的点击手指数目是一样的,默认值是为 0. */
    self.longPressGestureRecognizer.numberOfTouchesRequired = 2;
    /* Maximum 100 pixels of movement allowed before the gesture is recognized */
    /*最大100像素的运动是手势识别所允许的*/
    self.longPressGestureRecognizer.allowableMovement = 100.0f;
    /*这个参数表示,两次点击之间间隔的时间长度。*/
    self.longPressGestureRecognizer.minimumPressDuration = 1.0;
    [self.view addGestureRecognizer:self.longPressGestureRecognizer];
}

- (void) handleLongPressGestures:(UILongPressGestureRecognizer *)paramSender{
    if ([paramSender isEqual:self.longPressGestureRecognizer]){
        //如果按下手指数为2
        if (paramSender.numberOfTouchesRequired == 2){
            /********获得两个手指间的中点 Start********/
            CGPoint touchPoint1 = [paramSender locationOfTouch:0 inView:paramSender.view];
            CGPoint touchPoint2 = [paramSender locationOfTouch:1 inView:paramSender.view];
            CGFloat midPointX = (touchPoint1.x + touchPoint2.x) / 2.0f;
            CGFloat midPointY = (touchPoint1.y + touchPoint2.y) / 2.0f;
            CGPoint midPoint = CGPointMake(midPointX, midPointY);
            /********获得两个手指间的中点 End********/
            self.dummyButton.center = midPoint;
        }
    }
}
           

8、一个手势只能添加到一个View,两个View当然要有两个手势的实例了

- (void)viewDidLoad  
{  
    [super viewDidLoad];  
  
    UIImageView *snakeImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"snake.png"]];  
    UIImageView *dragonImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"dragon.png"]];  
    snakeImageView.frame = CGRectMake(120, 120, 100, 160);  
    dragonImageView.frame = CGRectMake(50, 50, 100, 160);  
    [self.view addSubview:snakeImageView];  
    [self.view addSubview:dragonImageView];  
      
    for (UIView *view in self.view.subviews) {  
        UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]  
                                                        initWithTarget:self  
                                                        action:@selector(handlePan:)];  
          
        UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc]  
                                                            initWithTarget:self  
                                                            action:@selector(handlePinch:)];  
          
        UIRotationGestureRecognizer *rotateRecognizer = [[UIRotationGestureRecognizer alloc]  
                                                         initWithTarget:self  
                                                         action:@selector(handleRotate:)];  
          
        [view addGestureRecognizer:panGestureRecognizer];  
        [view addGestureRecognizer:pinchGestureRecognizer];  
        [view addGestureRecognizer:rotateRecognizer];  
        [view setUserInteractionEnabled:YES];  
    }  
    [self.view setBackgroundColor:[UIColor whiteColor]];       
} 
           

9、自定义手势

自定义手势继承:UIGestureRecognizer,实现下面的方法:

– touchesBegan:withEvent:

– touchesMoved:withEvent:

– touchesEnded:withEvent:

- touchesCancelled:withEvent:

新建一个类,继承UIGestureRecognizer,代码如下:

//.h文件
#import <UIKit/UIKit.h>
typedef enum {
    DirectionUnknown = 0,
    DirectionLeft,
    DirectionRight
} Direction;
@interface HappyGestureRecognizer : UIGestureRecognizer
@property (assign) int tickleCount;
@property (assign) CGPoint curTickleStart;
@property (assign) Direction lastDirection;
@end
 
//.m文件
#import "HappyGestureRecognizer.h"   
#import <UIKit/UIGestureRecognizerSubclass.h>   
#define REQUIRED_TICKLES        2   
#define MOVE_AMT_PER_TICKLE     25   
  
@implementation HappyGestureRecognizer  
  
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  
    UITouch * touch = [touches anyObject];  
    self.curTickleStart = [touch locationInView:self.view];  
}  
  
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {  
      
    // Make sure we've moved a minimum amount since curTickleStart   
    UITouch * touch = [touches anyObject];  
    CGPoint ticklePoint = [touch locationInView:self.view];  
    CGFloat moveAmt = ticklePoint.x - self.curTickleStart.x;  
    Direction curDirection;  
    if (moveAmt < 0) {  
        curDirection = DirectionLeft;  
    } else {  
        curDirection = DirectionRight;  
    }  
    if (ABS(moveAmt) < MOVE_AMT_PER_TICKLE) return;  
      
    // 确认方向改变了   
    if (self.lastDirection == DirectionUnknown ||  
        (self.lastDirection == DirectionLeft && curDirection == DirectionRight) ||  
        (self.lastDirection == DirectionRight && curDirection == DirectionLeft)) {  
          
        // 挠痒次数   
        self.tickleCount++;  
        self.curTickleStart = ticklePoint;  
        self.lastDirection = curDirection;  
          
        // 一旦挠痒次数超过指定数,设置手势为结束状态   
        // 这样回调函数会被调用。   
        if (self.state == UIGestureRecognizerStatePossible && self.tickleCount > REQUIRED_TICKLES) {  
            [self setState:UIGestureRecognizerStateEnded];  
        }  
    }  
      
}  
  
- (void)reset {  
    self.tickleCount = 0;  
    self.curTickleStart = CGPointZero;  
    self.lastDirection = DirectionUnknown;  
    if (self.state == UIGestureRecognizerStatePossible) {  
        [self setState:UIGestureRecognizerStateFailed];  
    }  
}  
  
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  
{  
    [self reset];  
}  
  
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event  
{  
    [self reset];  
}  
  
@end 
           

调用自定义手势和上面一样,回调这样写:

- (void)handleHappy:(HappyGestureRecognizer *)recognizer{
    [self.hehePlayer play];
}
           

手势成功后播放呵呵笑的声音。在真机上运行,按住某个view,快速左右拖动,就会发出笑的声音了。

代码解析:

先获取起始坐标:curTickleStart

通过和ticklePoint的x值对比,得出当前的放下是向左还是向右。再算出移动的x的值是否比MOVE_AMT_PER_TICKLE距离大,如果太则返回。

再判断是否有三次是不同方向的动作,如果是则手势结束,回调。