本篇内容接上一篇iOS事件机制(一),本次主要介绍iOS事件中的多点触控事件和手势事件。
从上一篇的内容我们知道,在iOS中一个事件用一个UIEvent对象表示,UITouch用来表示一次对屏幕的操作动作,由多个UITouch对象构成了一个UIEvent对象。另外,UIResponder
是所有响应者的父类,UIView、UIViewController、UIWindow、UIApplication都直接或间接的集成了UIResponder。关于事件响应者链的传递机制在上一篇中也有阐述,如果你还不是很了解,可以先看看iOS事件机制(一)。
事件处理方法
UIResponder中定义了一系列对事件的处理方法,他们分别是:
- –(void)touchesBegan:(NSSet )touches withEvent:(UIEvent )event
- –(void)touchesMoved:(NSSet )touches withEvent:(UIEvent )event
- –(void)touchesEnded:(NSSet )touches withEvent:(UIEvent )event
- –(void)touchesCancelled:(NSSet )touches withEvent:(UIEvent )event
从方法名字可以知道,他们分别对应了屏幕事件的开始、移动、结束和取消几个阶段,前三个阶段理解都没问题,最后一个取消事件的触发时机是在诸如突然来电话或是系统杀进程时调用。这些方法的第一个参数定义了UITouch对象的一个集合(NSSet),它的数量表示了这次事件是几个手指的操作,目前iOS设备支持的多点操作手指数最多是5。第二个参数是当前的UIEvent对象。下图展示了一个UIEvent对象与多个UITouch对象之间的关系。
一、点击事件
首先,新建一个自定义的View继承于UIView,并实现上述提到的事件处理方法,我们可以通过判断UITouch的tapCount属性来决定响应单击、双击或是多次点击事件。
MyView.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
#import "MyView.h"
@implementation MyView
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *aTouch in touches) {
if (aTouch.tapCount == 2) {
// 处理双击事件
[self respondToDoubleTapGesture];
}
}
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void)respondToDoubleTapGesture
{
NSLog(@"respondToDoubleTapGesture");
}
@end
|
二、滑动事件
滑动事件一般包括上下滑动和左右滑动,判断是否是一次成功的滑动事件需要考虑一些问题,比如大部分情况下,用户进行一次滑动操作,这次滑动是否是在一条直线上?或者是否是基本能保持一条直线的滑动轨迹。或者判断是上下滑动还是左右滑动等。另外,滑动手势一般有一个起点和一个终点,期间是在屏幕上画出的一个轨迹,所以需要对这两个点进行判断。我们修改上述的MyView.m的代码来实现一次左右滑动的事件响应操作。
MyView.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
#import "MyView.h"
#define HORIZ_SWIPE_DRAG_MIN 12 //水平滑动最小间距
#define VERT_SWIPE_DRAG_MAX 4 //垂直方向最大偏移量
@implementation MyView
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *aTouch = [touches anyObject];
// startTouchPosition是一个CGPoint类型的属性,用来存储当前touch事件的位置
self.startTouchPosition = [aTouch locationInView:self];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *aTouch = [touches anyObject];
CGPoint currentTouchPosition = [aTouch locationInView:self];
// 判断水平滑动的距离是否达到了设置的最小距离,并且是否是在接近直线的路线上滑动(y轴偏移量)
if (fabsf(self.startTouchPosition.x - currentTouchPosition.x) >= HORIZ_SWIPE_DRAG_MIN &&
fabsf(self.startTouchPosition.y - currentTouchPosition.y) <= VERT_SWIPE_DRAG_MAX)
{
// 满足if条件则认为是一次成功的滑动事件,根据x坐标变化判断是左滑还是右滑
if (self.startTouchPosition.x < currentTouchPosition.x) {
[self rightSwipe];//右滑响应方法
} else {
[self leftSwipe];//左滑响应方法
}
//重置开始点坐标值
self.startTouchPosition = CGPointZero;
}
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
//当事件因某些原因取消时,重置开始点坐标值
self.
|