手势识别使用说明书

2016-08-22 » iOS开发基础

手势部分

UIGestureRecognizer介绍

常用子类

UIPanGestureRecognizer(拖动)

UIPinchGestureRecognizer(捏合)

UIRotationGestureRecognizer(旋转)

UITapGestureRecognizer(点按)

UILongPressGestureRecognizer(长按)

UISwipeGestureRecognizer(轻扫)

另外,可以通过继承 UIGestureRecognizer 类,实现自定义手势(手势识别器类)。

手势状态

5种连续型手势、一种离散型手势

离散型手势:一旦识别就无法取消,而且只会调用一次手势操作事件(UITapGestureRecognizer)

连续型手势:会多次调用手势操作事件,而且在连续手势识别后可以取消手势

手势状态枚举如下

public enum State : Int {

    case possible	// 尚未识别是何种手势操作(但可能已经触发了触摸事件),默认状态
    case began		// 手势已经开始,此时已经被识别,但是这个过程中可能发生变化,手势操作尚未完成
    case changed 	// 手势状态发生转变
    case ended 		// 手势识别操作完成(此时已经松开手指)
    case cancelled	// 手势被取消,恢复到默认状态
    case failed		// 手势识别失败,恢复到默认状态

    public static var recognized: UIGestureRecognizer.State { get } // 手势识别完成,同UIGestureRecognizerStateEnded
}
  • 对于离散型手势 UITapGestureRecgnizer 要么被识别,要么失败,点按(假设点按次数设置为1,并且没有添加长按手势)下去一次不松开则此时什么也不会发生,松开手指立即识别并调用操作事件,并且状态为3(已完成)。

  • 但是连续型手势要复杂一些,就拿旋转手势来说,如果两个手指点下去不做任何操作,此时并不能识别手势(因为我们还没旋转)但是其实已经触发了触摸开始事件,此时处于状态0;如果此时旋转会被识别,也就会调用对应的操作事件,同时状态变成1(手势开始),但是状态1只有一瞬间;紧接着状态变为2(因为我们的旋转需要持续一会),并且重复调用操作事件(如果在事件中打印状态会重复打印2)。松开手指,此时状态变为3,并调用1次操作事件。

常用属性方法

weak open var delegate: UIGestureRecognizerDelegate?
手势代理

open var isEnabled: Bool
是否有效

open var view: UIView? { get }
手势所在View

open var cancelsTouchesInView: Bool
默认是true。当识别到手势的时候,终止touchesCancelled:withEvent:或pressesCancelled:withEvent:发送的所有触摸事件。

open var delaysTouchesBegan: Bool //用panGes去验证就明显了
delaysTouchesBgan属性用于控制这个消息的传递时机,默认这个属性为NO,此时在触摸开始的时候,就会发消息给事件传递链,如果我们设置为YES,在触摸没有被识别失败前,都不会给事件传递链发送消息。

open var delaysTouchesEnded: Bool
而delaysTouchesEnded属性默认是YES,当设为YES时在手势识别结束后,会等待一个很短的时间,如果没有接收到新的手势识别任务,才会发送touchesEnded消息到事件传递链

allowedTouchTypes  //UITouchTpye
允许的触摸类型

allowedPressTypes // UIPressType
允许的按压类型

open var requiresExclusiveTouchType: Bool
能否同时只接受一种触摸类型,而不是能否同时只接受一种手势

open func location(in view: UIView?) -> CGPoint
获取当前触摸的点

open var numberOfTouches: Int { get }
获取触摸点数
 
open func location(ofTouch touchIndex: Int, in view: UIView?) -> CGPoint
获取某一个触摸点的触摸位置

UIGestureRecognizerDelegate

//开始进行手势识别时调用的方法,返回NO则结束,不再触发手势
optional public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool

//是否支持多手势触发,返回YES,则可以多个手势一起触发方法,返回NO则为互斥
optional public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool

//下面这个两个方法也是用来控制手势的互斥执行的
//这个方法返回YES,第一个手势和第二个互斥时,第一个会失效
optional public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool

//这个方法返回YES,第一个和第二个互斥时,第二个会失效
optional public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool

//手指触摸屏幕后回调的方法,返回NO则不再进行手势识别,方法触发等
optional public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool

//iOS 9之后出来的 按压
optional public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive press: UIPress) -> Bool

手势操作的使用

使用手势很简单,分为三步:

  1. 创建手势识别器对象实例。创建时,指定一个回调方法,当手势开始,改变、或结束时,执行回调方法。
  2. 设置手势识别器对象实例的相关属性(可选部分)
  3. 添加到需要识别的 View 中。每个手势只对应一个 View,当屏幕触摸在 View 的边界内时,如果手势和预定的一样,那就会执行回调方法。

PS:一个手势只能对应一个 View,但是一个 View 可以有多个手势。建议在真机上测试这些手势,模拟器操作不太方便,可能导致认为手势失效的情况。(模拟器测试捏合和旋转手势时,按住 option 键,再用触摸板或鼠标操作)