《iOS 6核心开发手册(第4版)》——1.1节触摸

  1. 云栖社区>
  2. 博客>
  3. 正文

《iOS 6核心开发手册(第4版)》——1.1节触摸

异步社区 2017-05-02 15:22:00 浏览781
展开阅读全文

本节书摘来自异步社区《iOS 6核心开发手册(第4版)》一书中的第1章,第1.1节触摸,作者 【美】Erica Sadun,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.1 触摸
iOS 6核心开发手册(第4版)
Cocoa Touch以可能最简单的方式实现直接操作。它把触摸事件发送给正在处理的视图。作为一名iOS开发人员,你将告诉视图如何做出响应。在深入研究姿势和姿势识别器之前,应该在这种底层触摸技术上打下坚实的基础。它提供了所有基于触摸的交互的必要组件。

每个触摸都会传达信息:触摸发生的位置(当前和以前的位置)、使用的是触摸的哪个阶段(在桌面应用程序中实质上是鼠标按下、鼠标移动和鼠标抬起,在直接操作世界中对应于手指或触摸按下、移动和抬起)、点按计数(例如,单点按/双点按)以及触摸发生的时间(通过一个时间戳)。

iOS使用所谓的响应者链(responder chain)来决定哪些对象应该处理触摸。顾名思义,响应者是响应事件的对象,它们充当那些事件的可能的管理者链。当用户触摸屏幕时,应用程序将寻找一个对象来处理这种交互。触摸将从一个视图传递到另一个视图,直到某个对象接管并响应那个事件为止。

在最基本的级别上,触摸及其信息存储在UITouch对象中,它们在UIEvent对象中作为组进行传递。每个对象代表单独一个触摸事件,其中包含单个或多个触摸。这依赖于你如何设置应用程序来做出响应(也就是说,你是否启用了Multi-Touch交互),以及用户如何触摸屏幕(即触摸点的物理数量)。

应用程序在视图或视图控制器类中接收触摸;它们二者都通过继承UIResponder类来实现触摸处理程序。你决定在什么位置处理和响应触摸。尝试在非响应者类中实现低级的姿势控制使许多iOS开发人员新手步履维艰。

在视图中处理触摸看上去似乎是违反直觉的。你可能期望把界面的外观(它的视图)与它响应触摸的方式(它的控制器)分隔开。此外,为直接触摸交互使用视图似乎与模型—视图—控制器(Model-View-Controller)的设计原则相矛盾,但它可能是必要的,并且有助于促进封装。

考虑处理多个触摸响应子视图的情况,比如棋盘上的游戏棋子。直接在视图类中构建交互行为允许给主应用程序发送语义上具有丰富意义的反馈,同时隐藏实现细节。例如,可以在交互序列的末尾通知模型把一个卒移到了王后的主教5处,而不会传送一系列的意义的矢量变化。通过隐藏游戏棋子在响应触摸时的移动方式,模型代码可以重点关注游戏语义,而不是视图位置更新。

绘图展示了在UIView类中工作的另一个原因。当应用程序处理任何类型的绘图操作以响应用户触摸时,需要在视图中实现触摸处理程序。与视图不同的是,视图控制器没有实现非常重要的drawRect:方法,而它是提供自定义的展示所需要的。

在视图控制器级别上工作也具有它的额外好处,无须把主要的处理行为放入辅助类实现中,把触摸管理直接添加到视图控制器中允许解释标准的姿势,比如点按并保持或者轻扫,其中这些姿势都是有意义的。这更好地把代码集中在一起,并且有助于把控制器交互直接绑定到应用程序模型上。

在下面几节和秘诀中,你将发现触摸如何工作,如何把它们纳入到应用程序中,以及如何把用户所看到的内容与他们同屏幕交互的方式联系起来。

1.1.1 阶段
触摸具有生命周期。每个触摸都可能经历5个阶段,它们代表触摸在界面内的进程。这些阶段如下。

UITouchPhaseBegan——当用户触摸屏幕时开始。
UITouchPhaseMoved——意味着触摸已经移到屏幕上。
UITouchPhaseStationary——指示触摸仍然保留在屏幕表面,但是自从前一个事件起还没有进行任何移动。
UITouchPhaseEnded——当触摸离开屏幕时触发。
UITouchPhaseCancelled——当iOS系统停止跟踪特定的触摸时发生。这通常是由于系统中断而发生的,比如当应用程序不再活动或者从窗口中删除视图时。
整体而言,这5个阶段构成了触摸事件的交互语言。它们描述了触摸在界面内向前推进或者无法推进的所有可能的方式,并且为那个界面提供了控制的基础。作为开发人员,由你决定如何解释这些阶段并提供对它们的反应,这是通过实现一系列响应者方法来完成的。

1.1.2 触摸和响应者方法
UIResponder类的所有子类(包括UIView和UIViewController)都会对触摸做出响应。每个类决定了是否以及如何做出响应。如果选择这样做,当用户在视图或窗口中按下一根或多根手指时,它们会实现自定义的行为。

预先定义的回调方法处理触摸的开始、移动以及从屏幕上移开等事件。与你已经看到的阶段相对应,涉及的方法如下。注意:UITouchPhaseStationary不会生成一个回调。

touchesBegan:withEvent:——当用户开始触摸屏幕时,在事件的开始阶段调用。
touchesMoved:withEvent:——处理手指随着时间的推移而进行的移动。
touchesEnded:withEvent:——结束触摸过程,其中将放开手指。它提供了一个合适的时间来清理在移动序列期间处理的任何工作。
touchesCancelled:WithEvent:——当Cocoa Touch必须对正在进行的触摸事件的系统中断做出响应时调用该方法。
上面的所有方法都是一个UIResponder方法,通常是在UIView或UIViewController子类中实现的。所有的视图都继承这些方法的基本的非功能版本。当向应用程序中添加触摸行为时,将重写这些方法,并且添加一个自定义的版本,提供应用程序需要的响应。

你的类可以实现所有这些方法,也可以只实现其中一些方法。对于真实的部署,将总是希望添加一个触摸取消事件,处理用户把手指拖离屏幕的情况,或者处理进入的电话呼叫的情况,它们都会取消正在进行的触摸序列。作为一个规则,一般可以把取消的触摸重定向到touchesEnded:withEvent:方法。这允许代码完成触摸序列,即使用户的手指没有离开屏幕。Apple建议:在处理触摸时重写全部4个方法,并将其作为一种最佳实践。

注意:
视图具有一种称为独占式触摸(exclusive touch)的模式,可以阻止把触摸传送给同一个窗口中的其他视图。当启用这种模式时,该属性将阻止其他视图接收触摸事件。主视图独占地处理所有的触摸事件。

1.1.3 触摸视图
在处理许多屏幕上的视图时,iOS将自动决定用户触摸的是哪个视图,并把任何触摸事件传递给正确的视图。这有助于编写具体的直接操作界面,其中用户将触摸、拖动屏幕上的对象并与之交互。

仅仅由于触摸物理上位于视图的顶部并不意味着视图必须做出响应。每个视图都可以使用“命中测试”来选择是否处理触摸,或者让该触摸落到它下面的视图上。在下面的秘诀中可以看到,能够使用聪明的响应策略来决定视图何时应该做出响应,尤其是当使用具有部分透明度的不规则艺术作品时。

对于触摸事件,传递命中测试的第一个视图倾向于处理或拒绝触摸。如果它通过了,触摸将继续到达该视图的父视图,并沿着响应者链传递,直至它被处理,或者它到达拥有视图的窗口为止。如果窗口没有处理它,触摸将转移到应用程序实例上,其中将处理或丢弃它。

注意:
触摸仅限于UIView及其子类,包括窗口。在开发面向iPhone 4S和更早的版本以及iPhone 5平台的应用程序时,要确保窗口扩展到个屏幕。在iPhone 5平台上最常见的问题出现在纵向模式中,并且应用程序无法响应屏幕底部的触摸。这发生在将应用程序的关键窗口调整到3.5"屏幕但是使用更大的4"模式时。如果没有支持性的窗口视图,将不会识别触摸。确保应用程序同时支持3.5"和4"屏幕,这可以通过把它们的关键UIWindow扩展到屏幕的完整垂直范围来实现。

1.1.4 多触摸
iOS同时支持单触摸和多触摸界面。单触摸GUI在任何时间只处理一个触摸。这减轻了你的责任,只需确定正在跟踪的是哪个触摸。你接收到的那个触摸是唯一需要处理的触摸。你查看它的数据,对它做出响应,并等待下一个事件。

在处理多触摸时,也就是说,在同时响应屏幕上的多个触摸时,将接收到完整的触摸集。由你决定如何对这个触摸集进行排序并做出响应。不过,你可以单独跟踪每个触摸,并且查看它如何随着时间的推移而改变,从而提供一组可能更丰富的用户交互。在本章后面给出了用于单触摸和多触摸交互的秘诀。

1.1.5 姿势识别器
利用姿势识别器,Apple添加了一种强大的方式来检测界面中的特定姿势。姿势识别器简化了触摸设计。它们封装了触摸方法,因此不必自己实现它们,并且提供了隐藏实现细节的目标-动作反馈机制。它们还标准化了对某些移动、拖动或轻扫等进行分类的方式。

利用姿势识别器类,可以在iOS感知到用户点按、捏合、旋转、轻扫、平移或长按时触发回调。尽管它们的软件开发工具包(Software Development Kit,SDK)实现不够尽善尽美,这些检测能力还是简化了基于触摸的界面的开发。你可以自己编码来改进可靠性,但是绝大多数开发人员将发现交付的识别器足够健壮,能满足许多应用程序的要求。你将在本章中发现多个基于识别器的秘诀。由于识别器基本上是以相同的方式工作,可以轻松地扩展这些秘诀,以满足特定的姿势识别需求。

下面列出了在近来的iOS SDK版本中构建的各类姿势。

点按——点按对应于屏幕上的一次或多次手指点按。用户可以利用一根或几根手指点按,可以指定需要多少根手指作为姿势识别器属性,以及希望检测多少次点按。可以创建一个点按识别器,用于处理一根手指的点按;或者创建差别更明显的识别器,用于寻找(例如)两根手指的三点按。
轻扫——轻扫是短暂的单个或多个触摸姿势,它们在单一基本方向上移动:向上、向下、向左或向右。它们不能偏离这个主方向太远。你可以设置希望识别器处理的方向,识别器将返回检测到的方向作为一个属性。
捏合——要捏合或取消捏合,用户必须在单独一次移动中把两根手指移到一起或分开它们。识别器返回一个比例因子,指示捏合的程度。
旋转——要进行旋转,用户必须在顺时针方向或逆时针方向上同时移动两根手指,产生一个角度旋转,作为主要的返回属性。
平移——平移发生在用户把手指拖过屏幕时。识别器确定由该拖动产生的平移中的变化。
长按——要创建长按姿势,用户可以触摸屏幕并把他或她的手指按下一段指定的时间。在识别器触发之前,可以指定必须使用多少根手指。

网友评论

登录后评论
0/500
评论
异步社区
+ 关注