文章目录

  • 概要介绍
  • UIGestureRecognizer创建方法
  • UIGestureRecognizer类常用属性以及方法
  • 点击手势
  • 使用
  • 一定要把视图的用户交互属性设置成YES
  • 捏合与旋转
  • 使用
  • 滑动手势
  • 使用
  • 拖动手势
  • 长按手势


概要介绍

在iphone模拟器上,按住option键这时就能模拟双指触摸了,只能模拟二指水平拖动,旋转效果。
按住option+shift键就能模拟捏合手势。
iOS 一共提供了6种类型的手势操作,分别为:点击,捏合,旋转,滑动,长按,手势需要添加到UIView控件及其子控件之上,同时每个UIView可以添加多个手势。
UIGestureRecognizer类是一个抽象类,不能直接使用。具体使用过程中需要使用其子类,UIGestureRecognizer一共包括6个子类,分别对应6种手势,即:

  • UITapGestureRecognizer:点击
  • UIPinchGestureRecognizer:捏合
  • UIRotationGestureRecognizer:旋转
  • UISwipeGestureRecognizer:滑动
  • UIPanGesturerecognizer:拖动,其又包含另外一个子类:UIScreenEdgePanGestureRecognizer
  • UILongPressGestureRecognizer:长按

UIGestureRecognizer创建方法

  • 创建一个UIView类对象
  • 创建一个手势类对象,并使用-initWithTarget:action:方法对对象初始化,设置当手势事件发生时,调用的方法。
  • 为UIView对象添加手势,使用addGestureRecongnizer方法
  • 实现手势事件发生时所调用的方法。

UIGestureRecognizer类常用属性以及方法

UIGestureRecognizer类虽然是一个抽象类,但是其中定义了其子手势类中可以通用的方法和属性。下面的几个方法是需要程序员重点掌握的。

初始化手势对象并设置手势发生时调用的方法
– (instancetype)initWithTarget:(nullable id)target action:(nullable SEL)action;

获取手势点击的位置
– (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view;

获取手势点击的状态和视图
@property(nonatomic,readonly) UIGestureRecognizerState state;
其中:常用的UIGestureRecognizerState有:
UIGestureRecognizerStateBegan:开始手势事件
UIGestureRecognizerStateEnded:结束手势事件
UIGestureRecognizerStateChanged:手势位置发生变化
UIGestureRecognizerStateFailed:无法识别的手势

手势事件对应的视图对象
@property(nullable, nonatomic,readonly) UIView *view;

点击手势

同时能够识别单击以及双击,甚至能够识别到使用几根手指进行点击。

需要点击的次数,用于识别单击或双击,默认为:单击

@property (nonatomic) NSUInteger  numberOfTapsRequired;

点击的手指数,默认为:1

@property (nonatomic) NSUInteger  numberOfTouchesRequired;

使用

一定要把视图的用户交互属性设置成YES

默认是NO:

self.imageView.userInteractionEnabled=YES;
//
//  ViewController.m
//  Gesture_base
//
//  Copyright © 2019 Shae. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.imageView.userInteractionEnabled=YES;
    
    //单击,单手指
    UITapGestureRecognizer *singleTap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(singleTap:)];
    //单击
    singleTap.numberOfTapsRequired=1;
    //单手指
    singleTap.numberOfTouchesRequired=1;
    //添加到imageView
    [self.imageView addGestureRecognizer:singleTap];
    
    //双击,双手指
    UITapGestureRecognizer *doubleTap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubleTap:)];
    //单击
    doubleTap.numberOfTapsRequired=2;
    //单手指
    doubleTap.numberOfTouchesRequired=2;
    //添加到imageView
    [self.imageView addGestureRecognizer:doubleTap];
    
    
}
-(void)singleTap:(UITapGestureRecognizer*)gesture{
    UIAlertController *alertController=[UIAlertController alertControllerWithTitle:@"单击+单手指" message:nil preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action=[UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleDefault handler:nil];
    [alertController addAction:action];
    [self presentViewController:alertController animated:YES completion:nil];
}
-(void)doubleTap:(UITapGestureRecognizer*)gesture{
    UIAlertController *alertController=[UIAlertController alertControllerWithTitle:@"双击+双手指" message:nil preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action=[UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleDefault handler:nil];
    [alertController addAction:action];
    [self presentViewController:alertController animated:YES completion:nil];
}
@end

捏合与旋转

捏合手势(UIPinchGestureRecognizer)与旋转手势(UIRotationGestureRecognizer)都可以通过修改UIView对象的transform属性,来实现UI控件的缩放和旋转。
捏合手势可以获取手势在屏幕坐标系中的缩放比例,根据该缩放比例,可以调整UIView控件的缩放。:

@property (nonatomic)   CGFloat scale;

旋转手势可以获取手势在屏幕坐标系中的旋转角度,根据该旋转角度,可以调整UIView控件的角度。

@property (nonatomic) CGFloat  rotation;

使用

捏合

//捏合手势
    UIPinchGestureRecognizer *pinchGesture=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
    [self.imageView addGestureRecognizer:pinchGesture];
-(void)pinch:(UIPinchGestureRecognizer*)gesture{
    NSLog(@"%f,scale: %f",__func__,gesture.scale);
    CGFloat scale=gesture.scale;
    self.imageView.transform=CGAffineTransformScale(gesture.view.transform, scale, scale);
    //不要使用 CGAffineTransformMake(),会有一些bug
    //一定要把scale的值重置为1,否则会影响缩放效果,即缩放比例会在上一次的基础上进行缩小/放大
    gesture.scale=1;
}

旋转

//旋转手势
    UIRotationGestureRecognizer *rotationGesture=[[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotation:)];
    [self.imageView addGestureRecognizer:rotationGesture];
-(void)rotation:(UIRotationGestureRecognizer*)gesture{
    NSLog(@"%s, rotation:%f, velocity:%f",__func__,gesture.rotation,gesture.velocity);
    CGFloat rotation=gesture.rotation;
    self.imageView.transform=CGAffineTransformRotate(gesture.view.transform, rotation);
    //一定要把rotation的值重置为0,否则会影响旋转效果。
    gesture.rotation=0;
}

滑动手势

滑动手势(UISwipeGestureRecognizer)常用于照片管理类App,能够实现照片的滑动显示。滑动手指支持向上、向下、向左、向右四个方面的滑动,在创建滑动手势对象时,需要通过direction属性来指定滑动的方向,默认的滑动方向为向右滑动。

@property(nonatomic) UISwipeGestureRecognizerDirection direction;

其中,UISwipeGestureRecognizerDirection的取值包括:

UISwipeGestureRecognizerDirectionRight:向右,默认;
UISwipeGestureRecognizerDirectionLeft:向左;
UISwipeGestureRecognizerDirectionUp:向上;
UISwipeGestureRecognizerDirectionDown:向下。

使用

实现图片管理,左滑和右滑实现图片的切换。
创建一个数组,数组里面存放图片。

@property (nonatomic,strong)NSMutableArray *imageList;

有个索引显示当前显示的图片的索引。

@property(nonatomic,assign)NSInteger imageIndex;
-(NSMutableArray *)imageList{
    if (_imageList==nil) {
        _imageList=[NSMutableArray array];
        for (int i=0; i<4; i++) {
            NSString *imageName=[NSString stringWithFormat:@"%d",i];
            UIImage *image=[UIImage imageNamed:imageName];
            [_imageList addObject:image];
        }
    }
    return _imageList;
}
_imageIndex=0;
    //滑动手势默认是向右的
    UISwipeGestureRecognizer *swipeRight=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
    [self.imageView addGestureRecognizer:swipeRight];
    
    UISwipeGestureRecognizer *swipeLeft=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
    swipeLeft.direction=UISwipeGestureRecognizerDirectionLeft;
    [self.imageView addGestureRecognizer:swipeLeft];

用懒加载的话,都要用self.的方式调用属性。

-(void)swipe:(UISwipeGestureRecognizer*)gesture{
    NSInteger imageCount=self.imageList.count;
    if (gesture.direction==UISwipeGestureRecognizerDirectionLeft) {
        if (_imageIndex>=imageCount-1) return;
        self.imageView.image=self.imageList[++_imageIndex];
    }else if (gesture.direction==UISwipeGestureRecognizerDirectionRight){
        if (_imageIndex<=0) return;
        self.imageView.image=self.imageList[--_imageIndex];
    }
}

拖动手势

拖动手势(UIPanGestureRecognizer)可以修改一个UI控件的位置,在有的游戏类APP中比较常见,拖动事件发生时,通过translationInView的方法,可以得到一个CGPoint类型的返回值,即位置的偏移量,可以根据偏移量修改对应的UI控件的center属性从而实现UI控件的位置移动效果。

//拖动手势
    UIPanGestureRecognizer *panGesture=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
    [self.imageView addGestureRecognizer:panGesture];
-(void)pan:(UIPanGestureRecognizer*)gesture{
    //获取位置变化量
    CGPoint translation=[gesture translationInView:self.view];
    gesture.view.center=CGPointMake(gesture.view.center.x+translation.x, gesture.view.center.y+translation.y);
    //要重置一下gesture的位置变化量
    [gesture setTranslation:CGPointZero inView:self.view];
}

拖动手势存在的时候,似乎滑动手势就不起作用了。

长按手势

通过长按手势(UILongPressGestureRecognizer)可以监控手势作用于UI控件的开始长按、长按过程中以及松开等状态,并且设置不同的动作。最常见的应用案例可以参考微信的对讲模式,按住按钮即可开始录音,松开后结束录音并发送给对方。长按手势一定需要和UIGestureRecognizer类的state属性进行配合使用,即通过不同状态state下,实现不同的功能。UIGestureRecognizer类的state属性中,常见的有,其实UIGestureRecognizer的所有子类都有这个属性:

UIGestureRecognizerStateBegan:开始手势事件
UIGestureRecognizerStateEnded:结束手势事件
UIGestureRecognizerStateChanged:手势位置发生变化
UIGestureRecognizerStateFailed:无法识别的手势

//长按手势
    UILongPressGestureRecognizer *longPressGesture=[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
    [self.imageView addGestureRecognizer:longPressGesture];
-(void)longPress:(UILongPressGestureRecognizer*)gesture{
    switch (gesture.state) {
        case UIGestureRecognizerStateBegan:
            NSLog(@"开始长按");
            self.stateLabel.text=[NSString stringWithFormat:@"开始长按......"];
            break;
        case UIGestureRecognizerStateEnded:
            NSLog(@"结束长按");
            self.stateLabel.text=@"结束长按";
            break;
            
        default:
            NSLog(@"长按中");
            self.stateLabel.text=@"长按中";
            break;
    }
}

代码:https://github.com/ShaeZhuJiu/UIGestureRecognizer_base.git