OC UI ------UIGestureRecognizer 手势识别
文章目录
- [OC UI ------UIGestureRecognizer 手势识别](#OC UI ——UIGestureRecognizer 手势识别)
- [一、什么是 UIGestureRecognizer?](#一、什么是 UIGestureRecognizer?)
-
- [1.1 定义](#1.1 定义)
- [1.2 好处](#1.2 好处)
- [1.3 手势识别的层级关系](#1.3 手势识别的层级关系)
- 二、手势识别核心原理:底层工作机制
-
- [2.1 手势识别的完整流程](#2.1 手势识别的完整流程)
- [2.2 手势识别器的核心状态(重点)](#2.2 手势识别器的核心状态(重点))
- [2.3 事件回调机制](#2.3 事件回调机制)
- 三、五大常用手势深度解析
-
- [3.1 UITapGestureRecognizer(点击手势)](#3.1 UITapGestureRecognizer(点击手势))
-
- [3.1.1 功能说明](#3.1.1 功能说明)
- [3.1.2 核心属性(重点)](#3.1.2 核心属性(重点))
- [3.1.3 完整代码演示(单击+双击)](#3.1.3 完整代码演示(单击+双击))
- [3.1.4 常见问题与解决方案](#3.1.4 常见问题与解决方案)
- [3.2 UILongPressGestureRecognizer(长按手势)](#3.2 UILongPressGestureRecognizer(长按手势))
-
- [3.2.1 功能说明](#3.2.1 功能说明)
- [3.2.2 核心属性(重点)](#3.2.2 核心属性(重点))
- [3.2.3 完整代码演示(长按弹出菜单)](#3.2.3 完整代码演示(长按弹出菜单))
- [3.2.4 关键注意点](#3.2.4 关键注意点)
- [3.3 UIPanGestureRecognizer(拖拽平移手势)](#3.3 UIPanGestureRecognizer(拖拽平移手势))
-
- [3.3.1 功能说明](#3.3.1 功能说明)
- [3.3.2 核心属性与方法](#3.3.2 核心属性与方法)
- [3.3.3 完整代码演示(拖拽视图自由移动)](#3.3.3 完整代码演示(拖拽视图自由移动))
- [3.3.4 进阶技巧](#3.3.4 进阶技巧)
- [3.4 UIPinchGestureRecognizer(捏合缩放手势)](#3.4 UIPinchGestureRecognizer(捏合缩放手势))
-
- [3.4.1 功能说明](#3.4.1 功能说明)
- [3.4.2 核心属性与方法](#3.4.2 核心属性与方法)
- [3.4.3 完整代码演示(双指缩放图片)](#3.4.3 完整代码演示(双指缩放图片))
- [3.4.4 关键注意点](#3.4.4 关键注意点)
- [3.5 UIRotationGestureRecognizer(旋转手势)](#3.5 UIRotationGestureRecognizer(旋转手势))
-
- [3.5.1 功能说明](#3.5.1 功能说明)
- [3.5.2 核心属性与方法](#3.5.2 核心属性与方法)
- [3.5.3 完整代码演示(双指旋转图片)](#3.5.3 完整代码演示(双指旋转图片))
- 四、手势识别高级用法
-
- [4.1 手势冲突的解决方法](#4.1 手势冲突的解决方法)
-
- [方法1:使用 requireGestureRecognizerToFail: 方法](#方法1:使用 requireGestureRecognizerToFail: 方法)
- 方法2:实现手势识别协议(UIGestureRecognizerDelegate)
- [方法3:调整手势的 enabled 属性](#方法3:调整手势的 enabled 属性)
- [4.2 自定义手势](#4.2 自定义手势)
一、什么是 UIGestureRecognizer?
1.1 定义
简单来说,我们之前通过 UIButton 实现点击交互,是"控件绑定事件";而手势识别是"脱离控件本身,直接监听屏幕动作"------无论是 View、ImageView、Label,甚至是空白区域,只要添加了手势识别器,就能响应对应的手指动作.
1.2 好处
在移动开发中,手势是用户与APP交互的主要方式之一,手势识别的核心价值体现在三个方面:
- 打破控件限制:无需依赖按钮、滑块等可交互控件,任意视图都能实现复杂交互(如长按图片保存、拖拽图标排序);
- 提升交互体验:模拟真实世界的操作逻辑(如双指缩放图片、旋转屏幕),让用户操作更自然、更流畅;
- 简化开发流程:系统封装了常用手势,无需手动监听触摸事件(如 touchBegan、touchMoved),大幅减少代码量,降低开发难度。
1.3 手势识别的层级关系
要理解手势识别,必须明确它与 View、ViewController 的层级关系,这是后续避免手势冲突、实现复杂交互的关键:
- 触摸事件的传递顺序:屏幕接收用户触摸 → 传递给 UIWindow → 传递给最上层的 View → 传递给该 View 上的手势识别器;
- 手势识别器的归属:手势识别器(UIGestureRecognizer)是"附加"在 View 上的,一个 View 可以添加多个手势识别器,一个手势识别器也可以附加到多个 View 上;
- 与触摸事件的优先级:手势识别器会"拦截"触摸事件------当用户的动作被手势识别器识别后,该触摸事件就不会再传递给 View 本身(如 View 的 touchMoved 方法不会再触发)。
二、手势识别核心原理:底层工作机制
2.1 手势识别的完整流程
手势识别的整个过程分为 5 个阶段,从用户触摸屏幕到触发回调,每一步都有明确的逻辑:
- 触摸开始:用户手指按下屏幕,系统将触摸事件传递给对应 View 上的手势识别器;
- 手势分析:手势识别器开始分析触摸动作的特征(如手指数量、移动轨迹、停留时间);
- 状态判断:根据分析结果,手势识别器切换自身状态(如从"可能识别"到"识别成功");
- 事件回调:当手势识别成功或失败时,触发绑定的回调方法,执行业务逻辑;
- 触摸结束:用户手指离开屏幕,手势识别器重置状态,等待下一次触摸事件。
2.2 手势识别器的核心状态(重点)
UIGestureRecognizer 有 6 种核心状态,所有手势的识别过程,本质上都是状态的切换过程。
| 状态枚举 | 状态说明 | 典型场景 |
|---|---|---|
| UIGestureRecognizerStatePossible | 初始状态,手势识别器准备就绪,等待触摸事件 | 手势刚被添加到 View 上,未接收任何触摸 |
| UIGestureRecognizerStateBegan | 手势开始被识别(如长按手势达到最小长按时间) | 长按手势,手指按下停留超过0.5秒(默认) |
| UIGestureRecognizerStateChanged | 手势识别中,动作发生变化(如拖拽时手指移动、缩放时双指距离变化) | 拖拽视图时,手指移动过程中;双指缩放图片时,手指距离变化 |
| UIGestureRecognizerStateEnded | 手势识别成功,手指离开屏幕 | 单击手势,手指按下后松开;拖拽手势,手指松开 |
| UIGestureRecognizerStateCancelled | 手势识别被取消(未完成识别) | 长按手势时,手指未松开就拖动到屏幕外;系统中断手势(如来电) |
| UIGestureRecognizerStateFailed | 手势识别失败(动作不符合手势要求) | 双击手势,两次点击间隔超过默认时间;拖拽手势,手指按下后未移动 |
补充:所有手势识别器的初始状态都是 Possible,最终会走向 Ended(成功)、Cancelled(取消)或 Failed(失败),且状态一旦切换到这三种,会自动重置为 Possible,等待下一次触摸。
2.3 事件回调机制
手势识别器的回调的核心是"绑定目标-动作"(Target-Action),与 UIButton 的回调机制类似,但更灵活------可以绑定多个目标和动作,也可以动态添加、移除回调。
核心原理:当手势识别器的状态发生变化(如 Began、Changed、Ended)时,系统会自动调用绑定的动作方法,并且会将手势识别器本身作为参数传递给方法,方便我们在方法中获取手势的状态、位置等信息。
三、五大常用手势深度解析
UIGestureRecognizer 是一个抽象基类,我们无法直接实例化,只能使用它的子类------系统已经封装了 5 个最常用的手势子类,覆盖了 90% 以上的开发场景。
3.1 UITapGestureRecognizer(点击手势)
3.1.1 功能说明
最基础、最常用的手势,用于识别用户的"单击""双击""多击"动作(如点击图片查看大图、双击点赞、三击放大文本)。
3.1.2 核心属性(重点)
- numberOfTapsRequired:需要点击的次数(默认1,单击;设为2,双击;设为3,三击);
- numberOfTouchesRequired:需要同时点击的手指数量(默认1,单指点击;设为2,双指点击);
- delaysTouchesEnded:是否延迟触摸结束事件(默认YES)------避免双击时,第一次点击的 Ended 事件被提前触发,导致双击识别失败。
3.1.3 完整代码演示(单击+双击)
objc
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UIImageView *imgView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 1. 创建图片视图(作为手势的载体)
self.imgView = [[UIImageView alloc] initWithFrame:CGRectMake(50, 100, 300, 200)];
self.imgView.image = [UIImage imageNamed:@"testImage"];
self.imgView.userInteractionEnabled = YES; // 关键:默认UIImageView不可交互,必须开启
[self.view addSubview:self.imgView];
// 2. 创建单击手势
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapAction:)];
singleTap.numberOfTapsRequired = 1; // 单击
singleTap.numberOfTouchesRequired = 1; // 单指
[self.imgView addGestureRecognizer:singleTap];
// 3. 创建双击手势
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapAction:)];
doubleTap.numberOfTapsRequired = 2; // 双击
[self.imgView addGestureRecognizer:doubleTap];
// 4. 解决单击与双击冲突:双击时,不触发单击(关键)
[singleTap requireGestureRecognizerToFail:doubleTap];
}
// 单击回调
- (void)singleTapAction:(UITapGestureRecognizer *)gesture {
NSLog(@"单击图片");
// 查看大图
UIImageView *bigImgView = [[UIImageView alloc] initWithFrame:self.view.bounds];
bigImgView.image = self.imgView.image;
bigImgView.userInteractionEnabled = YES;
bigImgView.backgroundColor = [UIColor blackColor];
[self.view addSubview:bigImgView];
// 给大图添加单击,点击关闭
UITapGestureRecognizer *closeTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeBigImg:)];
[bigImgView addGestureRecognizer:closeTap];
}
// 双击回调
- (void)doubleTapAction:(UITapGestureRecognizer *)gesture {
NSLog(@"双击图片");
// 放大图片
[UIView animateWithDuration:0.3 animations:^{
self.imgView.transform = CGAffineTransformScale(self.imgView.transform, 1.2, 1.2); // 放大1.2倍
}];
}
// 关闭大图回调
- (void)closeBigImg:(UITapGestureRecognizer *)gesture {
[gesture.view removeFromSuperview];
}
@end
3.1.4 常见问题与解决方案
- 问题1:UIImageView 添加手势后不响应?------ 忘记设置 userInteractionEnabled = YES(默认NO);
- 问题2:单击和双击冲突,双击时会先触发单击?------ 使用 requireGestureRecognizerToFail: 方法,让单击手势等待双击手势识别失败后再触发;
3.2 UILongPressGestureRecognizer(长按手势)
3.2.1 功能说明
识别用户"长按"动作,即手指按下屏幕后,停留一段时间不移动、不松开。常用场景:长按保存图片、长按删除图标、长按弹出菜单(如微信长按消息弹出删除/转发)。
3.2.2 核心属性(重点)
- minimumPressDuration:最小长按时间(默认0.5秒)------ 手指按下后,停留超过这个时间,才会触发手势;
- allowableMovement:允许的最大移动距离(默认10像素)------ 长按过程中,手指移动距离不超过这个值,手势仍会被识别;超过则识别失败;
- numberOfTouchesRequired:需要同时长按的手指数量(默认1,单指长按)。
3.2.3 完整代码演示(长按弹出菜单)
objc
- (void)viewDidLoad {
[super viewDidLoad];
// 1. 创建标签(载体)
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 350, 300, 40)];
label.text = @"长按我弹出菜单";
label.backgroundColor = [UIColor lightGrayColor];
label.userInteractionEnabled = YES;
label.tag = 100; // 加个tag方便识别
[self.view addSubview:label];
// 2. 创建长按手势
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressAction:)];
longPress.minimumPressDuration = 0.6;
longPress.allowableMovement = 15;
[label addGestureRecognizer:longPress];
}
// 必须实现:让控制器可以成为第一响应者
- (BOOL)canBecomeFirstResponder {
return YES;
}
// 必须实现:声明我们要响应哪些菜单方法
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (action == @selector(copyText:) || action == @selector(deleteText:)) {
return YES;
}
return NO;
}
// 长按回调
- (void)longPressAction:(UILongPressGestureRecognizer *)gesture {
if (gesture.state == UIGestureRecognizerStateBegan) {
NSLog(@"长按开始");
UILabel *targetLabel = (UILabel *)gesture.view;
// 让控制器成为第一响应者(必须)
[self becomeFirstResponder];
UIMenuController *menu = [UIMenuController sharedMenuController];
UIMenuItem *copyItem = [[UIMenuItem alloc] initWithTitle:@"复制" action:@selector(copyText:)];
UIMenuItem *deleteItem = [[UIMenuItem alloc] initWithTitle:@"删除" action:@selector(deleteText:)];
menu.menuItems = @[copyItem, deleteItem];
[menu setTargetRect:targetLabel.bounds inView:targetLabel];
[menu setMenuVisible:YES animated:YES];
}
}
// 复制点击事件
- (void)copyText:(UIMenuController *)menu {
NSLog(@"点击了复制");
UILabel *label = [self.view viewWithTag:100];
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = label.text;
}
// 删除点击事件
- (void)deleteText:(UIMenuController *)menu {
NSLog(@"点击了删除");
UILabel *label = [self.view viewWithTag:100];
label.text = @"";
}

3.2.4 关键注意点
长按手势的回调方法会多次触发(Began、Changed、Ended 等状态都会触发),因此必须通过判断 gesture.state,只在需要的状态(如 Began)执行逻辑,避免重复操作。
3.3 UIPanGestureRecognizer(拖拽平移手势)
3.3.1 功能说明
识别用户"拖拽"动作,即手指按下屏幕后,持续移动。常用场景:拖拽视图调整位置(如拖拽图标、拖拽滑块)、滑动删除、下拉刷新(简化版)。
3.3.2 核心属性与方法
- translationInView: 方法:获取手势在指定 View 中的平移距离(CGPoint 类型,x 为水平平移距离,y 为垂直平移距离);
- velocityInView: 方法:获取手势的移动速度(CGPoint 类型,单位:像素/秒);
- setTranslation: inView: 方法:重置平移距离(常用在拖拽过程中,避免平移距离累积);
- minimumNumberOfTouches:最小拖拽手指数量(默认1);
- maximumNumberOfTouches:最大拖拽手指数量(默认无限制)。
3.3.3 完整代码演示(拖拽视图自由移动)
objc
- (void)viewDidLoad {
[super viewDidLoad];
// 1. 创建可拖拽的视图
UIView *dragView = [[UIView alloc] initWithFrame:CGRectMake(50, 420, 100, 100)];
dragView.backgroundColor = [UIColor redColor];
dragView.userInteractionEnabled = YES;
[self.view addSubview:dragView];
// 2. 创建拖拽手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
pan.minimumNumberOfTouches = 1;
pan.maximumNumberOfTouches = 1;
[dragView addGestureRecognizer:pan];
}
// 拖拽回调
- (void)panAction:(UIPanGestureRecognizer *)gesture {
// 1. 获取拖拽的平移距离(相对于父视图)
CGPoint translation = [gesture translationInView:gesture.view.superview];
// 2. 计算视图的新位置(原位置 + 平移距离)
CGRect newFrame = gesture.view.frame;
newFrame.origin.x += translation.x;
newFrame.origin.y += translation.y;
// 3. 限制视图不能超出屏幕
CGFloat maxX = self.view.bounds.size.width - gesture.view.bounds.size.width;
CGFloat maxY = self.view.bounds.size.height - gesture.view.bounds.size.height;
newFrame.origin.x = MAX(0, MIN(newFrame.origin.x, maxX)); // 水平限制
newFrame.origin.y = MAX(0, MIN(newFrame.origin.y, maxY)); // 垂直限制
// 4. 更新视图位置
gesture.view.frame = newFrame;
// 5. 重置平移距离(关键:避免下次拖拽时,平移距离累积)
[gesture setTranslation:CGPointZero inView:gesture.view.superview];
// 6. 根据手势状态执行不同逻辑
if (gesture.state == UIGestureRecognizerStateEnded) {
// 拖拽结束,让视图轻微回弹
[UIView animateWithDuration:0.2 animations:^{
gesture.view.transform = CGAffineTransformScale(gesture.view.transform, 1.05, 1.05);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 animations:^{
gesture.view.transform = CGAffineTransformIdentity;
}];
}];
}
}
@end
3.3.4 进阶技巧
通过 velocityInView: 方法,可以实现"拖拽速度越快,视图移动越远"的效果(如拖拽结束后,根据速度让视图继续滑动一段距离),提升交互的流畅度。
3.4 UIPinchGestureRecognizer(捏合缩放手势)
3.4.1 功能说明
识别用户"双指捏合"或"双指张开"动作,用于调整视图的缩放比例。。
3.4.2 核心属性与方法
- scale:缩放比例(默认1.0,即原始大小;大于1.0放大,小于1.0缩小);
- velocity:缩放速度(单位:缩放比例/秒,正值表示放大,负值表示缩小);
- setScale: 方法:设置初始缩放比例;
- reset() 方法:重置缩放比例为1.0。
3.4.3 完整代码演示(双指缩放图片)
objc
- (void)viewDidLoad {
[super viewDidLoad];
self.imgView = [[UIImageView alloc] initWithFrame:CGRectMake(50, 100, 300, 200)];
self.imgView.image = [UIImage imageNamed:@"1"]; // 你的图片
self.imgView.userInteractionEnabled = YES;
self.imgView.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:self.imgView];
// 添加旋转手势
UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotationAction:)];
rotation.delegate = self;
[self.imgView addGestureRecognizer:rotation];
}
// 正确的旋转方法
- (void)rotationAction:(UIRotationGestureRecognizer *)gesture {
// 取当前手势的旋转角度
CGFloat rotation = gesture.rotation;
// 在现有 transform 基础上叠加旋转(关键写法)
gesture.view.transform = CGAffineTransformRotate(gesture.view.transform, rotation);
// 重置角度,防止叠加爆炸
gesture.rotation = 0;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES; // 允许多个手势同时生效
}
3.4.4 关键注意点
捏合手势的 scale 属性是"相对值"(相对于上一次回调的缩放比例),因此必须在每次回调后将 scale 重置为1.0,否则缩放比例会不断累积,导致缩放失控。
3.5 UIRotationGestureRecognizer(旋转手势)
3.5.1 功能说明
识别用户"双指旋转"动作,用于调整视图的旋转角度。常用场景:旋转图片、旋转控件(如自定义旋钮)、调整画板笔触方向。
3.5.2 核心属性与方法
- rotation:旋转角度(单位:弧度,默认0;正值表示顺时针旋转,负值表示逆时针旋转);
- velocity:旋转速度(单位:弧度/秒,正值顺时针,负值逆时针);
- setRotation: 方法:设置初始旋转角度;
- reset() 方法:重置旋转角度为0。
补充:iOS 中,弧度与角度的转换公式:弧度 = 角度 × π / 180;角度 = 弧度 × 180 / π。
3.5.3 完整代码演示(双指旋转图片)
objc
- (void)viewDidLoad {
[super viewDidLoad];
// 1. 创建图片视图
self.imgView = [[UIImageView alloc] initWithFrame:CGRectMake(50, 100, 300, 200)];
self.imgView.image = [UIImage imageNamed:@"testImage"];
self.imgView.userInteractionEnabled = YES;
self.imgView.contentMode = UIViewContentModeScaleAspectFit;
// 设置图片中心点(旋转中心,默认是视图中心)
self.imgView.layer.anchorPoint = CGPointMake(0.5, 0.5); // 中心旋转
[self.view addSubview:self.imgView];
// 2. 创建旋转手势
UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotationAction:)];
[self.imgView addGestureRecognizer:rotation];
}
// 旋转回调
- (void)rotationAction:(UIRotationGestureRecognizer *)gesture {
// 1. 获取当前旋转角度(弧度)
CGFloat currentRotation = gesture.rotation;
// 2. 计算新的旋转角度(累积之前的旋转角度)
CGFloat newRotation = gesture.view.transform.rotation + currentRotation;
// 3. 更新视图旋转
gesture.view.transform = CGAffineTransformMakeRotation(newRotation);
// 4. 重置旋转角度(关键:避免下次旋转时,角度累积)
gesture.rotation = 0.0;
}
@end
四、手势识别高级用法
4.1 手势冲突的解决方法
当一个 View 上添加多个手势,或多个 View 上的手势存在重叠时,会出现"手势冲突"(如单击与双击、拖拽与缩放)。解决手势冲突的核心是"设置手势的优先级"或"判断手势的触发条件",主要有 3 种方法:
方法1:使用 requireGestureRecognizerToFail: 方法
让一个手势等待另一个手势识别失败后,再触发自身。适用于"互斥手势"(如单击和双击)。
objc
// 让单击手势等待双击手势识别失败后,再触发
[singleTap requireGestureRecognizerToFail:doubleTap];
方法2:实现手势识别协议(UIGestureRecognizerDelegate)
通过协议方法,手动判断手势是否可以识别、是否允许同时识别多个手势,灵活控制手势的触发。常用协议方法:
- gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer::是否允许当前手势与其他手势同时识别(返回YES,允许同时识别;返回NO,不允许);
- gestureRecognizer:shouldReceiveTouch::是否允许手势接收触摸事件(可根据触摸位置、手指数量等条件,控制手势是否生效);
- gestureRecognizerShouldBegin::手势是否应该开始识别(返回YES,开始识别;返回NO,拒绝识别)。
objc
// 示例:解决拖拽与缩放手势的冲突,允许同时识别
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
// 判断两个手势是否是拖拽和缩放
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
return YES; // 允许同时识别,实现拖拽的同时缩放
}
return NO;
}
方法3:调整手势的 enabled 属性
根据业务逻辑,动态启用或禁用手势。例如:当图片放大到最大比例时,禁用缩放手势;当拖拽到屏幕边缘时,禁用拖拽手势。
objc
// 禁用缩放手势
self.pinchGesture.enabled = NO;
// 启用缩放手势
self.pinchGesture.enabled = YES;
4.2 自定义手势
系统提供的 5 个手势可以满足大部分场景,但如果需要实现特殊手势(如滑动轨迹识别、手势密码、双指拖拽),就需要自定义手势。
自定义手势的核心步骤:
- 创建 UIGestureRecognizer 的子类;
- 重写触摸事件方法(touchesBegan:withEvent:、touchesMoved:withEvent:、touchesEnded:withEvent:);
- 在触摸事件中,分析触摸动作的特征(如轨迹、手指数量);
- 根据特征,切换手势的状态(如识别成功则设置为 Ended);
- 绑定回调方法,执行业务逻辑。