一、响应者链

以UIResponder作为超类的任何类都是响应者。UIView和UIControl是UIReponder的子类,因此所有视图和所有控件都是响应者。

  • 初始相应器
    事件首先会传递给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 = ;
static CGFloat const kMaximmVariance = ; @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)( * 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)( * 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)( * 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)( * 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 = ; touchCount <= ; 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 :
return @"Single";
case :
return @"Double";
case :
return @"Triple";
case :
return @"Quadruple";
case :
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)( * 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)( * 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 = ;
singleTap.numberOfTouchesRequired = ;
// 附加到视图
[self.view addGestureRecognizer:singleTap]; UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap)];
doubleTap.numberOfTapsRequired = ;
doubleTap.numberOfTouchesRequired = ;
[self.view addGestureRecognizer:doubleTap];
// 当doubleTap响应“失败”才运行singleTap
[singleTap requireGestureRecognizerToFail:doubleTap]; UITapGestureRecognizer *tripleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tripleTap)];
tripleTap.numberOfTapsRequired = ;
tripleTap.numberOfTouchesRequired = ;
[self.view addGestureRecognizer:tripleTap];
[doubleTap requireGestureRecognizerToFail:tripleTap]; UITapGestureRecognizer *quadrupleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(quadrupleTap)];
quadrupleTap.numberOfTapsRequired = ;
quadrupleTap.numberOfTouchesRequired = ;
[self.view addGestureRecognizer:quadrupleTap];
[tripleTap requireGestureRecognizerToFail:quadrupleTap];
} - (void)singleTap
{
self.singleLabel.text = @"Single Tap Detected";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)( * 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)( * 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)( * 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)( * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.quadrupleLabel.text = @"";
});
} @end

五、检测捏合和旋转

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UIGestureRecognizerDelegate>

@end

ViewController.h

//
// 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 = ; 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 = ;
}
} - (void)doRorate:(UIRotationGestureRecognizer *)gesture
{
rotation = gesture.rotation;
[self transformImageView];
if (gesture.state == UIGestureRecognizerStateEnded) {
previousRotation = rotation + previousRotation;
rotation = ;
}
} @end

ViewController.m

六、自定义手势

//
// 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 = ;
static CGFloat const kMaximumCheckMarkAngle = ;
static CGFloat const kMinimumCheckMarkLength = ; @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

CheckMarkRecognizer.m

//
// 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)( * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.imageView.hidden = YES;
});
} @end

ViewController.m

iOS开发-轻点、触摸和手势的更多相关文章

  1. iOS开发系列之触摸事件

    基础知识 三类事件中触摸事件在iOS中是最常用的事件,这里我们首先介绍触摸事件. 在下面的例子中定义一个KCImage,它继承于UIView,在KCImage中指定一个图片作为背景.定义一个视图控制器 ...

  2. Android开发手记(30) 触摸及手势操作

    触摸操作在现在智能手机系统中起到举足轻重的作用,本文将对安卓中的触摸以及一些简单手势的操作进行简单的介绍. 1.触摸 首先是关于触摸的判断,有两种方法可以判断的触摸操作. (1)setOnTouchL ...

  3. ios开发-调用系统自带手势

    在 iPhone 或 iPad 的开发中,除了用 touchesBegan / touchesMoved / touchesEnded 这组方法来控制使用者的手指触控外,也可以用 UIGestureR ...

  4. iOS开发Quartz2D十二:手势解锁实例

    一:效果如图: 二:代码: #import "ClockView.h" @interface ClockView() /** 存放的都是当前选中的按钮 */ @property ( ...

  5. ios开发——实用技术OC-Swift篇&触摸与手势识别

    iOS开发学习之触摸事件和手势识别   iOS的输入事件 触摸事件 手势识别 手机摇晃 一.iOS的输入事件   触摸事件(滑动.点击) 运动事件(摇一摇.手机倾斜.行走),不需要人为参与的 远程控制 ...

  6. IOS 手势-轻点、触摸、手势、事件

    1.概念 手势是从你用一个或多个手指接触屏幕时开始,直到手指离开屏幕为止所发生的所有事件.无论手势持续多长时间,只要一个或多个手指仍在屏幕上,这个手势就存在. 触摸是指把手指放到IOS设备的屏幕上,从 ...

  7. iOS开发系列--触摸事件、手势识别、摇晃事件、耳机线控

    -- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以不用按键和手写笔直接操作的,这不愧为一项伟大的设计.今天我们就针对iOS的触摸事 ...

  8. iOS之触摸及手势

    触摸事件 iOS中的事件: 在用户使用app过程中,会产生各种各样的事件.iOS中的事件可以分为3大类型:    view的触摸事件处理: 响应者对象: 在iOS中不是任何对象都能处理事件,只有继承了 ...

  9. 转发:iOS开发系列--触摸事件、手势识别、摇晃事件、耳机线控

    -- iOS事件全面解析 转载来自崔江涛(KenshinCui) 链接:http://www.cnblogs.com/kenshincui/p/3950646.html 概览 iPhone的成功很大一 ...

随机推荐

  1. ios tweak之binary not signed (use ldid -S)问题解决

    参考tweak教程写了个简单的tweak,无奈完全无效果,摸索了好长时间才找到方法: 打开terminal ssh root@192.168.1.100 vim /var/log/syslog 找到如 ...

  2. 强大的日志分析工具 -- NSLogger

    转:http://www.cnblogs.com/yingkong1987/p/3329945.html 强大的日志分析工具 -- NSLogger 源码:https://github.com/fpi ...

  3. POJ 1068 Parencodings

    Parencodings Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24932   Accepted: 14695 De ...

  4. golang学习之指针、内存分配

    func pointer_test() { //空指针,输出为nil var p *int fmt.Printf("p: %v\n", p) //指向局部变量,变量值初始为0 va ...

  5. python学习资源

    12岁的少年教你用Python做小游戏: http://blog.jobbole.com/46308/ python视频教程大全集: http://www.douban.com/group/topic ...

  6. 再谈Jquery Ajax方法传递到action(转)

    之前写过一篇文章Jquery Ajax方法传值到action,本文是对该文的补充. 假设 controller中的方法是如下: public ActionResult ReadPerson(Perso ...

  7. 基于51,人体红外感应和RC522的门禁系统

    总结一下最近学的东西,这两天学的东西,rfid门卡系统终于弄出来来了,这个程序算现在写过的比较满意的程序,大家可以参考参考 主函数: #include<reg52.h> #include& ...

  8. rfid门禁系统笔记

    非接触式IC卡性能简介 主要指标: 1:容量为8K 位的EEPROM 2:分为16个扇区,每个扇区为4块,每块16个直接,以块为存取单位 3:每个扇区有独立的一组密码和访问控制 4:每张卡具有唯一的序 ...

  9. QT5.3+VS2013+QCustomPlot+QwtPlot+QwtPlot3D使用环境配置

    VS安装QT后运行环境所需配置 安装好QT和QT在VS下的插件之后: 1.打开VS,找到QT5→QT Option,如下: 2.配置电脑环境变量,在系统变量→Path下增加QT的动态库所在文件夹,也就 ...

  10. C++ 之高效使用STL ( STL 算法分类)

    http://blog.csdn.net/zhoukuo1981/article/details/3452118