您的位置:首页 > 移动开发 > IOS开发

The Core iOS CookBook 第一章节学习笔记 - 手势和触控

2015-09-02 00:00 387 查看
摘要: 触摸控制 是 iOS 系统交互的核心方式。

手势和触控基础知识

触摸控制 是 iOS 系统交互的核心方式。

触控

Cocoa Touch 以尽可能简单地方式实现了直接的操控。它会把触控事件发送给你正在进行交互的视图。
每一次触控都会转达很多的信息: 触控发生的位置,点击屏幕的次数,触控发生的时间。
iOS 使用 responder chain (响应链) 来确定究竟是哪个对象应该对触控做出响应。 响应者(responders)是响应 事件(event) 的对象。 这些响应者扮演的角色就好比是一串管理者,对这些 事件(event)进行管理。当用户触摸屏幕时,应用会去寻找一个对象来处理这一个触控事件。 触摸(touch)被传递下去,从一个视图到另外一个视图,直到一些对象来接管并且对这个 事件(event)做出响应。
在大多数情况下,触摸(touches)以及其信息 被存储在 UITouch 对象中,触摸(touches)被作为一组一组的形式在 UIEvent 对象中传递。每一个 UIEvent 对象都代表了一个单一的 触控事件,包含一次或多次触摸。这一点既决定了开发者如何去响应用户的操作,也决定了用户怎么在屏幕上进行操作。
你的应用通过 视图 或者 视图控制器 来接收 触摸(touches)。实现处理 触摸(touch)的类需要通过继承 UIResponder 类来实现。 你将会决定在哪儿处理和响应这些 触摸(touches)。 那些尝试不使用 responder 类来实现简单手势控制的开发新人会遇到很多麻烦。
在视图上处理 触摸(touches) 看似违反直觉。你可能想去把界面显示的方式和它对 touches 做出响应的方式分离开。进一步说,视图直接响应触控来实现交互看似违反了 MVC 设计模式,但是这样做是很有必要的,而且可以提高封装性。

阶段

touches 是具有生命周期的。任意一个 touch 都会经历五个阶段。

UITouchPhaseBegan - 当用户刚接触屏幕的时候

UITouchPhaseMoved - 当这个接触动作在屏幕上移动时

UITouchPhaseStationary - 当一个接触动作在屏幕上停止住时

UITouchPhaseEnded - 当用户的手指从屏幕上移开时

UITouchPhaseCancelled - 当 iOS 系统停止跟踪一个 touch 时。 通常发生在,系统中断或者是视图从窗口移除或者是处在非激活状态(有来电)。

这五个阶段用来划分一个触控事件发生过程中的整个流程。

触控和响应方法

所有 UIResponder 类的子类,包括 UIView 和 UIViewController 都会对 touches 做出响应。每一个类都决定了自身是否响应或者是如何去响应。当需要去做出响应时,这些类的实例会对用户的触控按照自己的方式进行响应。
预定义的回调方法能处理触控开始,触控移动,触控结束这几种情形。和 阶段(Phase)相对应。方法如下:

touchesBegan: withEvent: - 在触控刚刚发生的时候被调用

touchesMoved: withEvent: - 在触控移动的时候被调用

touchesEnded: withEvent: - 在触控结束的时候被调用

touchesCancelled: withEvent: - 当系统强行中断触控事件的时候,该方法会被调用(举例:你正在刷微博,突然有人来电,该方法就是在此刻被调用的)

上面的每一个方法都属于 UIResponder 方法,通常在 一个 UIView 或是 UIViewController 的子类中进行实现。 这些方法内部并没有实现什么功能。当你想把触控动作添加到应用时,就应该重载这些方法,实现自己需要的功能。 注意:在UITouchPhaseStationary 阶段,没有方法会被回调。

被触控的视图

多点触控

手势识别器

通过手势识别器类,当用户进行轻击、缩放、旋转、横扫、拖动或是一个长按动作时,我们可以触发回调方法。
几种常见的手势 1. Taps - 轻击,一指或多指 2. Swipes - 横扫 3. Pinches - 捏缩 4. Rotations - 双指进行视图的旋转 5. Pans - 拖拽进行平移 6. Long presses - 长按

方法1: 添加一个直接操作的界面

当你在处理直接操纵时,你的设计中心会由 UIViewController 移向 UIView. 更确切的说,应该是移向了 UIResponder。你通过自定义一个从UIResponder类中获取的方法,来创建一个可以进行触控的界面。
方法 1-1 这个例子创建了一个 UIImageView类的子类,名为 DragView,并且把触控响应添加到了这个子类中。 由于它是一个图片视图,它能够与用户进行交互就显得尤为重要(也就是说, setUserInteractionEnabled 属性必须被设置为 YES)。这个属性会影响这个视图本身以及它所有的子视图。代码如下:
@implementation DragView
{
CGPoint startLocation;
}

// 初始化方法
- (id)initWithImage:(UIImage *)image {

self = [super initWithImage:image];
if (self) {

// 在初始化成功后,让该 DragView 实例对象具备可交互性
self.userInteractionEnabled = YES;
}

return self;
}

// Responder 类中的接口方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

// 计算并且存储偏移量, 把相应触控的视图置顶
startLocation = [[touches anyObject] locationInView:self];
[self.superview bringSubviewToFront:self];
}

// Responder 类中的接口方法
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

// 计算偏移量
CGPoint point = [[touches anyObject] locationInView:self];
float dx = point.x - startLocation.x;
float dy = point.y - startLocation.y;

// 计算视图新的中心点坐标
CGPoint newCenter = CGPointMake(self.center.x + dx, self.center.y + dy);

// 确定视图新的位置
self.center = newCenter;
}


方法2:利用手势识别器,实现视图的手势控制

知识预备

AffineTransform 仿射变换 - 可以通过一系列的原子变换的复合来实现,包括:平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和错切(Shear)(图像的错切实际上是平面景物在投影平面上的非垂直投影)。

iOS 视图的 frame 和 bounds 属性的区别: http://blog.csdn.net/mad1989/article/details/8711697
frame: 该view在父view坐标系统中的位置和大小。(参照点是,父亲的坐标系统) bounds:该view在本地坐标系统中的位置和大小。(参照点是,本地坐标系统,就相当于ViewB自己的坐标系统,以0,0点为起点) center:该view的中心点在父view坐标系统中的位置和大小。(参照点是,父亲的坐标系统)
-(CGRect)frame{
return CGRectMake(self.frame.origin.x,self.frame.origin.y,self.frame.size.width,self.frame.size.height);
}
-(CGRect)bounds{
return CGRectMake(0,0,self.frame.size.width,self.frame.size.height);
}

Jan 4, 2015
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  iOS Gesture Touch