只要继承了UIResponder的对象就可作为事件的响应者,实际上UIControl继承了UIView,UIView又继承了UIResponder,由此可见,所有的对象都可作为事件的响应者。
当用户与某个控件交互时,该控件作为“第一响应者”,第一响应者作为响应者链的开始,该事件首先被发送给第一响应者。事件将沿着响应者链一直向下传播,直到被某个响应者处理。
通常来说,第一响应者都是UIView控件或UIView子类控件,当用户触摸该控件后,事件最先由该控件本身处理;如果该控件自身不处理时间,时间就会传播到它对应的视图控制器;如果视图控制器不处理该事件,事件就会传播到它对应的父视图控制器……直到顶层视图对应的视图控制器。
典型响应者链传播路线如下:
First Responder → FirstResponder的视图控制器 → 父容器 → 父容器的视图控制器→ UIWindow → UIApplication → 应用程序委托对象
如果某个事件经过上面完整的传播过程,依然没有被处理,那么该事件就会被丢弃。一般来说,上面响应者链的任何响应者处理该事件,该事件就会停止传播。
如果某个响应者“截获”了某个事件,那么该响应者要根据条件决定是否处理该事件。当响应者无法处理该事件时,则需要再处理方法中手动传力该事件。
如果希望自定义控件可以响应用户的触碰事件,则可以通过UIResPonder的如下4个方法实现:
(1) -touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event:当用户手指开始接触控件或窗口时激发该方法。
(2) -touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event:当用户手指在控件上移动时激发该方法。
(3) -touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event:当用户手指结束触碰控件时激发该方法。
(4) -touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event:当系统事件终止了触碰事件时激发该方法。
重写这些触碰事件处理方法时,第一个NSSet类型的参数代表了用户同时触碰控件的多个手指。
UITouch对象代表一个触碰事件,该对象提供了一个tapCount属性,该属性用于返回用户触碰屏幕的次数。
至于获取UITouch事件之后程序应该针对触碰事件进行何种处理,则完全取决于用户需要。
除此之外,iOS为手指触碰事件提供了手势处理器,通过手势处理器可使用一致的变成模式来处理各种触碰事件,而且变成更加简单,因此一般推荐用户使用手势处理器来处理用户触碰事件。
通过手势处理器处理用户触碰事件更加简单,而且无论处理那种触碰手势,都可面向UIGestureRecognizer编程,其子类如下:
(1) UITapGestureRecognizer:处理用户点击手势的手势处理器。
(2) UIPinchGestureRecognizer:处理用户捏合手势的手势处理器。
(3) UIRotationGestureRecognizer:处理用户旋转手势的手势处理器。
(4) UISwipeGestureRecognizer:处理用户活动手势的手势处理器。
(5) UIPanGestureRecognizer:处理用户拖动手势的手势处理器。
(6) UILongPressGestureRecognizer:处理用户长按的手势处理器。
使用手势处理器用户触碰手势的编程步骤如下:
(1) 根据程序要处理的手势创建对应的手势处理对象。
(2) 如果该UI控制不允许用户交互,则将该控件的userInteracionEnabled属性设为YES,如果支持多点触碰,则还需将multipleTouchEnabled设为YES。
(3) 调用UI控件的addGestureRecognizer:方法添加手势处理器。
UITapGestureRecognizer还提供了两个属性:
(1) numberOfTapsRequired:指定该手势处理器只处理几次触碰事件。
(2) numberOfTouchesRequired:指定该手势处理器只处理几个手指的触碰事件。
在用户使用两个手指在屏幕上捏合的过程中,程序可通过UIPinchGestureRecognizer检测到用户的这种捏合手势。
使用UIPinchGestureRecognizer步骤与UITapGestureRecognizer相同,定义了如下两个属性获取捏合相关信息:
(1) scale:获取捏合比例。
(2) velocity:获取捏合的速度。
如果用户使用两个手指在屏幕上旋转,程序可通过UIRotationGestureRecognizer检测到用户的这种旋转手势。
使用UIRotationGestureRecognizer处理手势的步骤与使用其他手势处理器的步骤完全相同。UIRotationGestureRecognizer定义了如下两个属性来获取旋转相关信息:
(1) rotation:获取旋转角度。
(2) velovity:获取旋转速度。
当用户使用一个或多个手指快速“扫”过屏幕时,程序可通过UISwipeGestureRecognizer检测到用户的这种轻扫手势。
使用UISwipeGestureRecognizer处理轻扫手势的步骤与使用其他手势处理器的步骤完全相同。UISwipeGestureRecognizer定义了如下两个属性来设置相关信息:
(1) direction:设置手势处理器处理该方向的轻扫。
(2) numberOfTouchesRequired:指定该手势处理器只处理几个手指的触碰事件。
在用户使用一个或多个手指在屏幕上拖动的过程中,程序可通过UIPanGestureRecognizer检测到用户的这种拖动手势。
使用UIPanGestureRecognizer处理拖动手势的步骤能使用其他手势处理器的步骤完全相同。UIPanGestureRecognizer定义如下两个属性来设置该手势处理器的相关信息:
(1) maximumNumberOfTouches:设置该拖动手势处理最多支持几个手指拖动。
(2) minimumNumberOfTouches:设置该拖动手势处理器最少需要几个手指一起拖动。
除此之外,该手势处理器还提供如下方法来获取拖动相关信息:
(1)-translationInView:获取该拖动手势在指定控件上的位移。
(2)-velocityInViwe:获取该拖动手势在指定控件上的拖动速度。
在用户使用一个或多个手指在屏幕上长按、不松开的过程中,程序可通过UILongPressGestureRecognizer检测用户的这种长按手势。
使用UILongPressGestureRecognizer处理长按手势的步骤与使用其他手势处理器的步骤:
(1) minimumPressDuration:指定用户至少在屏幕上按下多少秒才会触发该长按手势。
默认值为0.5。
(2) numberOfTouchesRequired:指定必须使用几个手指在屏幕上长按才会触发该手势。
(3) allowableMovement:指定该长按手势允许用户移动手指的最大距离。
开发自定义手势处理器的步骤如下:
(1) 创建继承UIGestureRecognizer的子类。
(2) 重写UIGestureRecognizer基类的触碰相关的四个方法。
在用户使用一个或多个手指在屏幕上水平摆动的过程中,程序可通过FKSwingGestureRecognizer检测用户的摆动手势。
在使用FKSwingGestureRecognizer处理摆动手势的步骤与使用其他手势处理器的步骤完全相同。FKSwingGestureRecognizer定义了如下属性来设置该手势处理器的相关信息:
swingCount:设置该拖动手势处理器要求用户手指至少摆动几次。
在涉及到表单输入的界面中,我们通常需要监听一些键盘事件,并根据实际需要来执行相应的操作。在UIWindow.h中定义了6个通知常量配合键盘处理:
(1) UIKeyboardWillShowNotification:键盘显示前。
(2) UIKeyboardDidShowNotification:键盘显示之后。
(3) UIKeyboardWillHideNotification:键盘隐藏之前。
(4) UIKeyboardDidHideNotification:键盘隐藏之后。
(5) UIKeyboardWillChangeFrameNotification:键盘大小改变之前。
(6) UIKeyboardDidChangeFrameNotification:键盘大小改变之后。
这几个通知的object对象都是nil,而userInfo字典都包含了一些键盘的信息,主要是键盘的位置大小信息。
需要注意的是,如果是在两个大小相同的键盘之间切换,则不会发送任何消息。如果是普通键盘中类似一中英文键盘的切换,只要大小改变了,都会发送一组或多组流程信息。