iOS 触摸事件五:手势处理器

本文详细介绍iOS中各种手势识别器的使用方法,包括点击、捏合、拖拽等常见手势的处理方式,以及如何通过设置属性实现特定功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过touches方法监听触摸事件,不容易区分用户的具体手势行为。为此,苹果推出了手势处理器(UIGestureRecognizer)。手势处理器处理用户触摸事件更加简单,而且无论处理哪种触摸手势,都可以面向GestureRecognizer编程。个人认为手势处理器即为手势触摸四个方法的一种封装。
平时我们使用手势处理器一般不直接使用UIGestureRecognizer,而是使用UIGesturerecognizer提供的六大子类来处理具体的手势:
- UITapGestureRecognizer: 处理用户点击手势的手势处理器
- UIPinchGestureRecognizer: 处理用户捏合手势的手势处理器
- UIPanGestureRecognizer: 处理用户拖拽手势的手势处理器
- UISwipeGestureRecognizer: 处理用户轻扫手势的手势处理器
- UIRotationGestureRecognizer: 处理用户旋转手势的手势处理器

手势处理器的处理用户触摸手势的步骤:

  1. 根据程序要处理的手势创建对应的手势处理器对象。创建手势处理器时需要指定target和action参数(当该控件上发生触摸手势后,该Target对象的action方法将会被激发,即目标-行为模式)
  2. 如果该UI控件不允许用户交互,则将该UI控件的userInteractionEnabled的属性设置为YES; 如果希望该空间可支持多点触摸,还需要将mutipleTouchEnable(是否多点触摸)设置为YES
  3. 调用该UI控件的addGestureRecognizer:方法添加该手势处理器

UIGestureRecognizer提供的一些常用方法和属性:

UIGestureRecognizer作为所有手势处理器的基类,提供了一些常用的方法和属性:
  - (CGPoint)locationInView:(UIView*)view; //返回该手势在view控件中的触摸位置
  - (NSUInteger)numberOfTouches;   // 返回该手势包含触摸点的数量(就是用户用了几个手指进行触摸)
  - view:  返回激发该收拾的UI控件
  - enabled: 用于设置和返回该手势处理器是否可用
  - state:  只读,获取该收拾的状态,(枚举值)比如
      手势刚刚开始处于UIGestureRecognizerStateBegan状态
      手势改变时处于UIGestureRecognizerStateChanged状态
      手势结束时处于UIGestureRecognizerStateEnded状态     

UITapGestureRecognizer:

点击手势的手势处理器,继承了UIGEstureRecognizer类,除了拥有父类的属性方法外,还提供了如下的两个属性:
  numberOfTapsRequired: 指定该手势处理器只处理几次触摸事件,默认是1
  numberOfTouchesRequired: 指定该手势处理器只能处理几个手指触摸事件,默认是1  
  使用:
   1. 创建Tap手势
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selecor(handlePanGesture:)]; 
//对手势进行初始化,并指定出发该手势时的所出发(调用)的handlePanGesture:方法。 同时会传递一个UIPanGestureRecognizer类型的参数
   2. 对手势的设置(可选)
    tapGesture.numberOfTouchesRequired = 1;//设置手势需要的触点的数量
    tapGesture.numberOfTapsRequired = 1; //设置手势需要点击的次数
   3. 将手势添加到UI控件上
//调用UIView的addGestureRecognizer:方法即可
[self.view addGestureRecognizer:tapGesture];

 //手势触发时调用的方法   
-(void)handlePanGesture:(UIPanGestureRecognizer *)gesture{
  NSLog(@"点击手势");
}

UIPinchGestureRecognizer:

   捏合手势,同样继承了UIRespond类,使用步骤和点击手势处理器完全相同,额外增加了两个属性来获取相关信息:
   scale :获取捏合的比例
   velocity : 获取捏合的速度
捏合手势一般用于图片的缩放。处理是要设置一下,避免缩放的速度过快。
   使用:
    //打开imgView的交互
    _imgView.userInteractionEnabled = YES;
    //打开imgView多点触摸 ,前提,多触点事件,要打开控件的多点触摸
    _imgView.multipleTouchEnabled = YES;
    //创建手势, target-action
      UIPinchGestureRecognizer *gesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];

    //为imgView添加手势
    [_imgView addGestureRecognizer:gesture];
    }

//手势处理函数
-(void)handlePinch:(UIPinchGestureRecognizer *)gesture{
    //手势处理
    NSLog(@"缩放。。");
    //获取捏合的比例
    CGFloat scale = gesture.scale;
    //直接缩放
   // _imgView.transform = CGAffineTransformMakeScale(scale, scale);  //--第二次缩放时回到原来
    //相对某个tranform进行缩放-- 在原有的基础上进行缩放
    _imgView.transform = CGAffineTransformScale(_imgView.transform, scale, scale) ;//--缩放的速度太快
    //优化。让缩放比例变为1,避免缩放过快
    gesture.scale = 1.0f;
}

UIPanGestureRecognizer:

 拖拽手势, 该手势设置相关信息的属性:
   maximumNumberOfTouches: 设置该手势处理器最多支持几个手指拖动
   minimumNumberOfTouches: 设置该手势处理器最少需要几个手指拖动
   translationInView: 获取拖动手势在指定控件上的位移。该方法返回一个CGPoint类型,该结构体中的x值代表水平方向的位移,y的值代表垂直方向上的位移
   velocityInView: 获取该拖动手势在指定控件上的拖动速度,该方法返回一个CGPoint类型,该结构体中的x值代表水平方向的移动速度,y的值代表垂直方向上的移动速度
   `
   - (void)viewDidLoad {
   [super viewDidLoad];

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];

pan.maximumNumberOfTouches = 3; //设置手势最多支持3个手指触点
pan.minimumNumberOfTouches = 1; //设置手势至少1个手指触点

[_imgView addGestureRecognizer:pan];

}

-(void)handleAction:(UIPanGestureRecognizer *)gesture{

CGPoint offSet = [gesture translationInView:_imgView];

//判断边界

_imgView.transform = CGAffineTransformTranslate(_imgView.transform, offSet.x, offSet.y);
[gesture setTranslation:CGPointMake(0,0) inView:_imgView];

}

   `

UISwipeGestureRecognizer:

  轻扫手势,获取与轻扫相关的信息:
    numberOfTouchesRequired: 设置该手势只处理几个手指的触摸事件
    direction: 设置该手势处理器只处理某个方向的轻扫,该属性支持上、下、左、右4个枚举值,一个手势处理器只能设置一个方向
    示例         `- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.

imgView = [[UIImageView alloc] initWithFrame:CGRectMake(SCREEN.size.width/2-32, SCREEN.size.height/2-32, 32,32)];
imgView.image = [UIImage imageNamed:@"a0_.9.png"];

UISwipeGestureRecognizer *swip = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip.numberOfTouchesRequired = 1; //需要一个触点
swip.direction = UISwipeGestureRecognizerDirectionUp;

UISwipeGestureRecognizer *swip1 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip1.numberOfTouchesRequired = 1; //需要一个触点
swip1.direction = UISwipeGestureRecognizerDirectionRight;

UISwipeGestureRecognizer *swip2 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip2.numberOfTouchesRequired = 1; //需要一个触点
swip2.direction = UISwipeGestureRecognizerDirectionDown;

UISwipeGestureRecognizer *swip3 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip3.numberOfTouchesRequired = 1; //需要一个触点
swip3.direction = UISwipeGestureRecognizerDirectionLeft;

[self.view addSubview:imgView];
[self.view addGestureRecognizer:swip];
[self.view addGestureRecognizer:swip1];
[self.view addGestureRecognizer:swip2];
[self.view addGestureRecognizer:swip3];

}

-(void)handleAction:(UISwipeGestureRecognizer *)gesture{

CGRect rect = imgView.frame;
NSLog(@"rect.x = %.2f, rect.y = %.2f", rect.origin.x, rect.origin.y);
if(gesture.direction == UISwipeGestureRecognizerDirectionUp ){
    //向上
     NSLog(@"向上");
    if(rect.origin.y >= 120){
        rect.origin.y -= 20;
    }else{
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到头了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
        [alert show];
    }
}
if(gesture.direction == UISwipeGestureRecognizerDirectionRight){
    //向右
     NSLog(@"向右");
    if(rect.origin.x+32 <= 270){
        rect.origin.x += 20;
    }else{
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到头了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
        [alert show];
    }

}
if(gesture.direction == UISwipeGestureRecognizerDirectionDown){
    //向下
      NSLog(@"向下");
    if(rect.origin.y+32 <= 500){
        rect.origin.y += 20;
    }else{
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到头了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
        [alert show];
    }

}
if(gesture.direction == UISwipeGestureRecognizerDirectionLeft){
    //向左
      NSLog(@"向左");
    if(rect.origin.x >= 20){
        rect.origin.x -= 20;
    }else{
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到头了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
        [alert show];
    }

}
imgView.frame = rect;

}`

UIRotationGestureRecognizer:

  旋转手势,额外定义了2个属性来获取旋转的相关信息:
   rotation: 获取旋转的角度
   velocity: 获取旋转的速度
  旋转手势同样经常用于图片的旋转处理,同样优化一下,避免旋转过快
   使用与上类似:
    - (void)viewDidLoad {
    [super viewDidLoad];

    UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotation:)];

   _imgView.userInteractionEnabled = YES;           _imgView.multipleTouchEnabled   = YES;

    [_imgView addGestureRecognizer:rotation];
}

-(void)handleRotation:(UIRotationGestureRecognizer *)gesture{
    NSLog(@"旋转");
    //获取旋转的角度
    CGFloat rotation = gesture.rotation;

    //对图片进行旋转
    _imgView.transform = CGAffineTransformRotate(_imgView.transform, rotation);

    //优化,避免旋转过快
    gesture.rotation = 0.0f;

}

UILongPressGestureRecognizer:

长按手势,设置相关信息的属性:
minmumPressDuration: 指定用户至少在屏幕上按下多少秒才会触发长按手势,默认值是0.5秒
allowableMovement:指定该长按手势允许用户移动手指的最大距离。如果用户手指按下时的移动距离超过了该距离,则长按手势失效
numberOfTouchesRequired: 指定必须使用几个手指在屏幕上长按才会触发该手势


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    //定义3个自定义的菜单项
    transmitItem = [[UIMenuItem alloc] initWithTitle:@"转发" action:@selector(transmitClick:)];
    deleteItem = [[UIMenuItem alloc] initWithTitle:@"删除" action:@selector(deleteClick:)];
    reportItem = [[UIMenuItem alloc] initWithTitle:@"举报" action:@selector(reportClick:)];

    //创建手势处理器,指定该控制器使用的行为方法
    UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressAction:)];
    _imgView.userInteractionEnabled = YES;
    //为视图添加手势
    [_imgView addGestureRecognizer:longPressGesture];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*自定义菜单项的点击事件*/
-(void)transmitClick:(id)sender{
    NSLog(@"点击转发");
}
-(void)deleteClick:(id)sender{
    NSLog(@"点击删除");
}
-(void)reportClick:(id)sender{
    NSLog(@"点击举报");
}
/*end*/

/*手势处理器的action函数, 当该方法被激活时,手势处理器会作为参数传递给该方法的参数*/
-(void)handleLongPressAction:(UILongPressGestureRecognizer *)gesture{
    //"开始触摸状态"时进入
    if(gesture.state == UIGestureRecognizerStateBegan){
        NSLog(@"长按手势触发");
        [self becomeFirstResponder];
        //创建一个menu控制器
        UIMenuController *menu = [UIMenuController sharedMenuController];
        menu.menuItems = @[transmitItem, deleteItem, reportItem];

        //悬浮在哪一个view上(定位Menu)并确定其大小
        CGRect rect = CGRectMake(0, 0, 100, 50);
        [menu setTargetRect:rect inView:_imgView];

        //展示Menu
        [menu setMenuVisible:YES];
    }
}
/*end*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值