一、响应者链
以UIResponder作为超类的任何类都是响应者。UIView和UIControl是UIReponder的子类,因此所有视图和所有控件都是响应者。
1、初始相应器
事件首先会传递给UIApplication对象,接下来会传递给应用程序的UIWindow,UIWindow会选择一个初始相应器来处理事件。初始响应器会选择下面的方式选择1、对于触摸事件,UIWindow会确定用户触摸的视图,然后将事件交给注册了这个视图的手势识别器或则注册视图层级更高的手势识别器。只要存在能处理事件的识别器,就不会再继续找了。如果没有的话,被触摸视图就是初始相应器,事件也会传递给它。
2、对于用户摇晃设备产生的或者是来自远程遥控设备事件,将会传递给第一响应器
如果初始响应器不处理时间,它会将事件传递给它的父视图(如果存在的话),或者传递给视图控制器(如果此视图是视图控制器的视图)。如果视图控制器不处理事件,它将沿着响应器链的层级继续传给父视图控制器(如果存在的话)。
如果在整个视图层级中都没与能处理事件的视图或控制器,事件就会被传递给应用程序的窗口。如果窗口不能处理事件,而应用委托是UIResponder的子类,UIApplication对象就会将其传递给应用程序委托。最后,如果应用委托不是UIResponder的子类,或者不处理这个事件,那么这个事件将会被丢弃。
4个手势通知方法
#pragma mark - Touch Event Methods // 用户第一次触摸屏幕时被调用 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { } // 当发生某些事件(如来电呼叫)导致手势中断时被调用 - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { } // 当用户手指离开屏幕时被调用 - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { } // 当用户手指移动时触发 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { }
二、检测扫描事件
1、手动检测
// // ViewController.m // Swipes // // Created by Jierism on 16/8/4. // Copyright © 2016年 Jierism. All rights reserved. // #import "ViewController.h" // 设置检测范围 static CGFloat const kMinimmGestureLength = 25; static CGFloat const kMaximmVariance = 5; @interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *label; @property (nonatomic) CGPoint gestureStartPoint; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; self.gestureStartPoint = [touch locationInView:self.view]; } - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint currentPosition = [touch locationInView:self.view]; // 返回一个float的绝对值 CGFloat deltaX = fabsf(self.gestureStartPoint.x - currentPosition.x); CGFloat deltaY = fabsf(self.gestureStartPoint.y - currentPosition.y); // 获得两个增量后,判断用户在两个方向上移动过的距离,检测用户是否在一个方向上移动得足够远但在另一个方向移动得不够来形成轻扫动作 if (deltaX >= kMinimmGestureLength && deltaY <= kMaximmVariance) { self.label.text = @"Horizontal swipe detected"; // 2s后擦除文本 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.label.text = @""; }); }else if (deltaY >= kMinimmGestureLength && deltaX <= kMaximmVariance){ self.label.text = @"Vertical swipe detected"; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.label.text = @""; }); } } @end
2、识别器检测
// // ViewController.m // Swipes // // Created by Jierism on 16/8/4. // Copyright © 2016年 Jierism. All rights reserved. // #import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *label; @property (nonatomic) CGPoint gestureStartPoint; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //创建两个手势识别器 // 1、水平方向识别器 UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportHorizontalSwipe:)]; horizontal.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight; [self.view addGestureRecognizer:horizontal]; // 2、垂直方向识别器 UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportVerticalSwipe:)]; vertical.direction = UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown; [self.view addGestureRecognizer:vertical]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer { self.label.text = @"Horizontal swipe detected"; // 2s后擦除文本 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.label.text = @""; }); } - (void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer { self.label.text = @"Vertical swipe detected"; // 2s后擦除文本 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.label.text = @""; }); } @end
三、实现多指轻扫
// // ViewController.m // Swipes // // Created by Jierism on 16/8/4. // Copyright © 2016年 Jierism. All rights reserved. // #import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *label; @property (nonatomic) CGPoint gestureStartPoint; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. for (NSUInteger touchCount = 1; touchCount <= 5; touchCount++) { //创建两个手势识别器 // 1、水平方向识别器 UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportHorizontalSwipe:)]; horizontal.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight; [self.view addGestureRecognizer:horizontal]; // 2、垂直方向识别器 UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportVerticalSwipe:)]; vertical.direction = UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown; [self.view addGestureRecognizer:vertical]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (NSString *)descriptionForTouchCount:(NSUInteger)touchCount { switch (touchCount) { case 1: return @"Single"; case 2: return @"Double"; case 3: return @"Triple"; case 4: return @"Quadruple"; case 5: return @"Quintuple"; default: return @""; } } - (void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer { self.label.text = [NSString stringWithFormat:@"%@ Horizontal swipe detected",[self descriptionForTouchCount:[recognizer numberOfTouches]]]; // 2s后擦除文本 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.label.text = @""; }); } - (void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer { self.label.text = [NSString stringWithFormat:@"%@ Vertical swipe detected",[self descriptionForTouchCount:[recognizer numberOfTouches]]]; // 2s后擦除文本 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.label.text = @""; }); } @end
四、检测多次轻点
// // ViewController.m // TapTaps // // Created by Jierism on 16/8/4. // Copyright © 2016年 Jierism. All rights reserved. // #import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *singleLabel; @property (weak, nonatomic) IBOutlet UILabel *doubleLabel; @property (weak, nonatomic) IBOutlet UILabel *tripleLabel; @property (weak, nonatomic) IBOutlet UILabel *quadrupleLabel; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 创建4个点击手势识别器 UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap)]; singleTap.numberOfTapsRequired = 1; singleTap.numberOfTouchesRequired = 1; // 附加到视图 [self.view addGestureRecognizer:singleTap]; UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap)]; doubleTap.numberOfTapsRequired = 2; doubleTap.numberOfTouchesRequired = 1; [self.view addGestureRecognizer:doubleTap]; // 当doubleTap响应“失败”才运行singleTap [singleTap requireGestureRecognizerToFail:doubleTap]; UITapGestureRecognizer *tripleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tripleTap)]; tripleTap.numberOfTapsRequired = 3; tripleTap.numberOfTouchesRequired = 1; [self.view addGestureRecognizer:tripleTap]; [doubleTap requireGestureRecognizerToFail:tripleTap]; UITapGestureRecognizer *quadrupleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(quadrupleTap)]; quadrupleTap.numberOfTapsRequired = 4; quadrupleTap.numberOfTouchesRequired = 1; [self.view addGestureRecognizer:quadrupleTap]; [tripleTap requireGestureRecognizerToFail:quadrupleTap]; } - (void)singleTap { self.singleLabel.text = @"Single Tap Detected"; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.singleLabel.text = @""; }); } - (void)doubleTap { self.doubleLabel.text = @"Double Tap Detected"; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.doubleLabel.text = @""; }); } - (void)tripleTap { self.tripleLabel.text = @"Triple Tap Detected"; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.tripleLabel.text = @""; }); } - (void)quadrupleTap { self.quadrupleLabel.text = @"Quadruple Tap Detected"; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.quadrupleLabel.text = @""; }); } @end
五、检测捏合和旋转
#import <UIKit/UIKit.h> @interface ViewController : UIViewController<UIGestureRecognizerDelegate> @end
// // ViewController.m // PinchMe // // Created by Jierism on 16/8/4. // Copyright © 2016年 Jierism. All rights reserved. // #import "ViewController.h" @interface ViewController () @property (strong,nonatomic) UIImageView *imageView; @end @implementation ViewController // 当前缩放比例,先前缩放比例 CGFloat scale,previousScale; // 当前旋转角度,先前旋转角度 CGFloat rotation,previousRotation; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. previousScale = 1; UIImage *image = [UIImage imageNamed:@"yosemite-meadows"]; self.imageView = [[UIImageView alloc] initWithImage:image]; // 对图像启用交互功能 self.imageView.userInteractionEnabled = YES; self.imageView.center = self.view.center; [self.view addSubview:self.imageView]; // 建立捏合手势识别器 UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(doPinch:)]; pinchGesture.delegate = self; [self.imageView addGestureRecognizer:pinchGesture]; // 建立旋转手势识别器 UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(doRorate:)]; rotationGesture.delegate = self; [self.imageView addGestureRecognizer:rotationGesture]; } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { // 允许捏合手势和旋转手势同时工作。否则,先开始的手势识别器会屏蔽另一个 return YES; } // 根据手势识别器中获得的缩放比例和旋转角度对图像进行变换 - (void)transformImageView { CGAffineTransform t = CGAffineTransformMakeScale(scale * previousScale, scale * previousScale); t = CGAffineTransformRotate(t, rotation + previousRotation); self.imageView.transform = t; } - (void)doPinch:(UIPinchGestureRecognizer *)gesture { scale = gesture.scale; [self transformImageView]; if (gesture.state == UIGestureRecognizerStateEnded) { previousScale = scale * previousScale; scale = 1; } } - (void)doRorate:(UIRotationGestureRecognizer *)gesture { rotation = gesture.rotation; [self transformImageView]; if (gesture.state == UIGestureRecognizerStateEnded) { previousRotation = rotation + previousRotation; rotation = 0; } } @end
六、自定义手势
// // CheckMarkRecognizer.m // CheckPlease // // Created by Jierism on 16/8/4. // Copyright © 2016年 Jierism. All rights reserved. // #import "CheckMarkRecognizer.h" #import "CGPointUtils.h" #import <UIKit/UIGestureRecognizerSubclass.h> // 一个重要目的是使手势识别器的state属性可写,子类将使用这个机制断言我们所观察的手势已成功完成 // 设置检测范围 static CGFloat const kMinimunCheckMarkAngle = 80; static CGFloat const kMaximumCheckMarkAngle = 100; static CGFloat const kMinimumCheckMarkLength = 10; @implementation CheckMarkRecognizer{ // 前两个实例变量提供之前的线段 CGPoint lastPreviousPoint; CGPoint lastCurrentPoint; // 画出的线段长度 CGFloat lineLengthSoFar; } // 用lastPreviousPoint和lastCurrentPoint组成第一条线段,跟第二条线段形成角度去完成手势 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView:self.view]; lastPreviousPoint = point; lastCurrentPoint = point; lineLengthSoFar = 0.0; } - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [super touchesMoved:touches withEvent:event]; UITouch *touch = [touches anyObject]; CGPoint previousPoint = [touch previousLocationInView:self.view]; CGPoint currentPoint = [touch locationInView:self.view]; CGFloat angle = angleBetweenLines(lastPreviousPoint, lastCurrentPoint, previousPoint, currentPoint); if (angle >= kMinimunCheckMarkAngle && angle <= kMaximumCheckMarkAngle && lineLengthSoFar > kMinimumCheckMarkLength) { self.state = UIGestureRecognizerStateRecognized; } lineLengthSoFar += distanceBetweenPoints(previousPoint, currentPoint); lastPreviousPoint = previousPoint; lastCurrentPoint = currentPoint; } @end
// // ViewController.m // CheckPlease // // Created by Jierism on 16/8/4. // Copyright © 2016年 Jierism. All rights reserved. // #import "ViewController.h" #import "CheckMarkRecognizer.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. CheckMarkRecognizer *check = [[CheckMarkRecognizer alloc] initWithTarget:self action:@selector(doCheck:)]; [self.view addGestureRecognizer:check]; self.imageView.hidden = YES; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)doCheck:(CheckMarkRecognizer *)check { self.imageView.hidden = NO; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.imageView.hidden = YES; }); } @end
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
手势事件 Tabris.js有基于4种手势类型的13种手势事件: tap - 手指短暂地触摸控件时,触发一次。 longpress - 手指触摸控件一定时间(约一秒,取决于平台),抬起手指时触发。 pan - 当手指向任一方向移动一定距离(约5px,取决于平台)时,就开始连续触发。事件始终在触摸的第一个元素上触发,即使手指移动到控件之外。 panLeft - 当手指向左移动一定距离时,就开始连续触
iOS 版Safari 为了向开发人员传达一些特殊信息,新增了一些专有事件。因为iOS 设备既没有鼠标也没有键盘,所以在为移动Safari 开发交互性网页时,常规的鼠标和键盘事件根本不够用。随着Android中的WebKit 的加入,很多这样的专有事件变成了事实标准,导致W3C 开始制定Touch Events 规范(参见https://dvcs.w3.org/hg/webevents/raw-f
本文向大家介绍Android触摸及手势操作GestureDetector,包括了Android触摸及手势操作GestureDetector的使用技巧和注意事项,需要的朋友参考一下 现在的智能手机不敢说百分百的都是触摸屏,也应该是百分之九九以上为触摸屏了,触摸屏为我们操作无键盘、无鼠标的手机系统带来了很多的便利。当用户触摸屏幕时会产生很多的触摸事件,down、up、move等等。View类有个Vie
本文向大家介绍Android手势滑动实现两点触摸缩放图片,包括了Android手势滑动实现两点触摸缩放图片的使用技巧和注意事项,需要的朋友参考一下 学习安卓手势滑动,多点触摸放大缩小图片,分享给大家供大家参考,具体代码如下 1.布局文件如下main.xml 2.自定义缩放图片控件ZoomImageView.java代码: 3.工程主文件MainActivity.java代码: 以上就是Androi
本文向大家介绍JS触摸事件、手势事件详解,包括了JS触摸事件、手势事件详解的使用技巧和注意事项,需要的朋友参考一下 触屏已经是我们身边电子设备的常态了。触摸事件当然也是随着触屏的出现,用户使用最多的事件啦! 难道使用触屏事件后,其他原来的鼠标事件就都不能用啦?当然不是,只不过不是那么好用啊。 针对鼠标事件,有哪些不适应? dbclick 触屏设备不支持双击事件。双击浏览器窗口,会放大画面。 可以通
本文向大家介绍iOS开发之手势识别,包括了iOS开发之手势识别的使用技巧和注意事项,需要的朋友参考一下 一、UIGestureRecognizer简单介绍 我们已经学习了触摸事件处理,但触摸事件处理起来很麻烦,每个触摸事件处理都需要实现3个touches方法,比较繁琐,实际上我们可以使用更加简单的触摸事件处理操作,那就是 手势识别UIGestureRecognizer 。 手势识别操作基类UIGe