iOS开发-轻点、触摸和手势
一、响应者链
以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开发-轻点、触摸和手势的更多相关文章
- iOS开发系列之触摸事件
基础知识 三类事件中触摸事件在iOS中是最常用的事件,这里我们首先介绍触摸事件. 在下面的例子中定义一个KCImage,它继承于UIView,在KCImage中指定一个图片作为背景.定义一个视图控制器 ...
- Android开发手记(30) 触摸及手势操作
触摸操作在现在智能手机系统中起到举足轻重的作用,本文将对安卓中的触摸以及一些简单手势的操作进行简单的介绍. 1.触摸 首先是关于触摸的判断,有两种方法可以判断的触摸操作. (1)setOnTouchL ...
- ios开发-调用系统自带手势
在 iPhone 或 iPad 的开发中,除了用 touchesBegan / touchesMoved / touchesEnded 这组方法来控制使用者的手指触控外,也可以用 UIGestureR ...
- iOS开发Quartz2D十二:手势解锁实例
一:效果如图: 二:代码: #import "ClockView.h" @interface ClockView() /** 存放的都是当前选中的按钮 */ @property ( ...
- ios开发——实用技术OC-Swift篇&触摸与手势识别
iOS开发学习之触摸事件和手势识别 iOS的输入事件 触摸事件 手势识别 手机摇晃 一.iOS的输入事件 触摸事件(滑动.点击) 运动事件(摇一摇.手机倾斜.行走),不需要人为参与的 远程控制 ...
- IOS 手势-轻点、触摸、手势、事件
1.概念 手势是从你用一个或多个手指接触屏幕时开始,直到手指离开屏幕为止所发生的所有事件.无论手势持续多长时间,只要一个或多个手指仍在屏幕上,这个手势就存在. 触摸是指把手指放到IOS设备的屏幕上,从 ...
- iOS开发系列--触摸事件、手势识别、摇晃事件、耳机线控
-- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以不用按键和手写笔直接操作的,这不愧为一项伟大的设计.今天我们就针对iOS的触摸事 ...
- iOS之触摸及手势
触摸事件 iOS中的事件: 在用户使用app过程中,会产生各种各样的事件.iOS中的事件可以分为3大类型: view的触摸事件处理: 响应者对象: 在iOS中不是任何对象都能处理事件,只有继承了 ...
- 转发:iOS开发系列--触摸事件、手势识别、摇晃事件、耳机线控
-- iOS事件全面解析 转载来自崔江涛(KenshinCui) 链接:http://www.cnblogs.com/kenshincui/p/3950646.html 概览 iPhone的成功很大一 ...
随机推荐
- BrowserSync,调试利器--自动刷新(转
---恢复内容开始--- 请想象这样一个场面:你开着两个显示器,一边是IDE里的代码,另一边是浏览器里的你正在开发的应用.此时桌上还放着你的手机,手机里也是这个开发中的应用.然后,你新写了一小段代码, ...
- System.arraycopy方法
数组的复制有多种方法,其中有一种就是System.arraycopy方法,传闻速度也很快. 方法完整签名: public static void arraycopy(Object src, int s ...
- 【转】No JVM could be found on your system解决方法
原文网址:http://my.oschina.net/liusicong/blog/324964 在安装android studio时,报错: Error launching android Stud ...
- android moveTaskToback 应用退到后台,类似最小化
方法:public boolean moveTaskToBack(boolean nonRoot) activity里有这个方法,参数说明如下: nonRoot=false→ 仅当activity为t ...
- UVALive 4255 Guess
这题竟然是图论···orz 题意:给出一个整数序列a1,a2,--,可以得到如下矩阵 1 2 3 4 1 - + 0 + 2 + + + 3 - - 4 + &quo ...
- matlab 学习
http://blog.sina.com.cn/s/blog_7086379501012pc5.html <a href = "http://blog.sina.com.cn/s/bl ...
- webdriver(python)学习笔记六——操作测试对象
定位到具体对象后,就需要对其进行操作,比如点击.输入内容等. 一般来说,webdriver中比较常用的操作对象的方法有下面几个 click 点击对象 send_keys 在对象上模拟按键输入 clea ...
- NIS Edit&Nsis打包程序发布(安装和卸载)
转自:http://blog.csdn.net/signjing/article/details/7855855 注意:首选得明确自己需要打包的程序,以及程序需要的dll文件,资源文件等. 1.下载N ...
- 【windows核心编程】一个HOOK的例子
一.应用场景 封装一个OCX控件,该控件的作用是来播放一个视频文件,需要在一个进程中放置四个控件实例. 由于控件是提供给别人用的,因此需要考虑很多东西. 二.考虑因素 1.控件的父窗口resize时需 ...
- 【跟我一起学Python吧】python with statement 进阶理解
由于之前有一个项目老是要打开文件,然后用pickle.load(file),再处理...最后要关闭文件,所以觉得有点繁琐,代码也不简洁.所以向python with statement寻求解决方法.以 ...