UIGestureRecognizer手势识别详解

来源:互联网 发布:苹果免费打电话软件 编辑:程序博客网 时间:2024/05/18 01:28

        iOS应用开发过程,合理的使用手势识别功能来响应用户的操作,能够很好提升用户体验,为App增色。下面对UIGestureRecognizer手势进行一个比较全面的描述:  

    

       1、UIGestureRecognizer介绍

            UIGestureRecognizer是手势识别的一个抽象类,没法直接使用。好心的苹果大神们已经为我们实现了常用的一些手势识别子类,具体列表如下:

  • UITapGestureRecognizer                               
  • UIPinchGestureRecognizer                            
  • UIRotationGestureRecognizer                        
  • UISwipeGestureRecognizer                            
  • UIPanGestureRecognizer                               
  • UIScreenEdgePanGestureRecognizer(iOS7.0以后)           
  • UILongPressGestureRecognizer                    

       1.1、UITapGestureRecognizer介绍
             用以识别用户使用单指或多指在某个View中点击一次或多次的动作。UITapGestureRecognizer除了包含继承自父类的属性外,还有两个自有属性:
             numberOfTapsRequired:          表示点击的次数,当连续点击次数未达到指定数量时,不作响应,默认值为1。
             numberOfTouchesRequired:    表示需同时点击的手指数量,默认值为1。
       1.2、UIPinchGestureRecognizer介绍
             用以识别用户使用两指在某个View中向外或向内滑动动作,平时多用于缩放。UIPinchGestureRecognizer除了包含继承自父类的属性外,还有两个自有属性:
             scale:表示缩放率
             velocity:表示缩放率对应的每秒速率(只读)
        1.3、UIRotationGestureRecognizer介绍
             用以识别用户使用两指在某个View中旋转动作。UIRotationGestureRecognizer除了包含继承自父类的属性外,还有两个自有属性:
             rotation:  表示旋转的弧度
             velocity:表示旋转弧度对应的每秒速率(只读)
         1.4、UISwipeGestureRecognizer介绍
             用以识别用户使用手指在某个View中的滑动动作,即快速移动。UISwipeGestureRecognizer除了包含继承自父类的属性外,还有两个自有属性:
             direction:表示滑动方向,向左、向右、向上、向下共四个方向
             numberOfTouchesRequired:表示需同时滑动的手指数量,默认值为1。
         1.5、UIPanGestureRecognizer介绍
             用以识别用户使用单指或多指在某个View中慢速移动动作。UIPanGestureRecognizer除了包含继承自父类的属性外,还有两个自有属性:
             minimumNumberOfTouches:表示最小手指数量,默认值为1
      maximumNumberOfTouches:表示最大手指数量,默认值为无符号整型的最大值
    1.6、UIScreenEdgePanGestureRecognizer介绍
      继承自UIPanGestureRecognizer,只是需要指定拖动动作的起始点距离屏幕边缘的位置。UIScreenEdgePanGestureRecognizer除了包含继承自父类的属性外,还有一个自有属性:
      edges:手势起始的位置区域
    1.7、UILongPressGestureRecognizer介绍
      用以识别用户使用单指或多指在某个View中长按的动作。UILongPressGestureRecognizer除了包含继承自父类的属性外,还有四个自有属性:
      minimumPressDuration:最短按下的时间,默认值为0.5秒。
      numberOfTouchesRequired:表示需同时滑动的手指数量,默认值为1。
      numberOfTapsRequired:表示点击的次数,默认值为1。
      allowableMovement:表示长按过程中手指允许移动的长度,计量单位为像素点,默认值为10像素点

       2、UIGestureRecognizer使用通用步骤

             UIGestureRecognizer使用非常简单,只需要两步即可完成:

             A、创建UIGestureRecognizer使用实例,指定对应的回调方法,此处以UITapGestureRecognizer为例说明

                  

        //创建UITapGestureRecognizer实例对象
        let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "handlePan:")

        //实现回调方法
        func handlePan(sender: UITapGestureRecognizer) {            print("get tap gesture")        }
             B、将UIGestureRecognizer实例对象添加进指定的View。一个手势只能对应一个View,但是一个View可以有多个手势

                 

        self.view.addGestureRecognizer(tapGesture)
                 多个View,只需向同一个View中继续添加UIGestureRecognizer实例对象即可

                 

        self.view.addGestureRecognizer(rotationGesture)

         3、自定义手势

              自定义手势需要继承UIGestureRecognizer类,并实现下面的方法

             

       - touchesBegan:withEvent:     //手势开始,当用户单指或多指触碰到屏幕       - touchesMoved:withEvent:     //手势移动,当用户单指或多指在屏幕上移动       - touchesEnded:withEvent:     //手势结束,当用户手指离开屏幕       - touchesCancelled:withEvent: //手势取消,如系统内存不足导致的取消等
        下面的例子为自定义的Tap手势实现代码,仅供学习之用

            

////  CustomTapGestureRecoginizer.swift//  Gest////  Created by jimi on 15/12/28.//  Copyright © 2015年 jimi. All rights reserved.//import UIKitimport UIKit.UIGestureRecognizerSubclassclass CustomTapGestureRecoginizer: UIGestureRecognizer {    var numberOfTapsRequired: Int = 1    var numberOfTouchesRequired: Int = 1        var firstLocation: CGPoint = CGPointZero        override init(target: AnyObject?, action: Selector) {        super.init(target: target, action: action)    }        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) {        super.touchesBegan(touches, withEvent: event)        if touches.count != self.numberOfTouchesRequired {            self.state = UIGestureRecognizerState.Failed        }                if let touch: UITouch = touches.first {//得到手指点击的起始位置            self.firstLocation = touch.locationInView(self.view)        }    }        override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent) {        super.touchesMoved(touches, withEvent: event)        if let touch: UITouch = touches.first {            let currentPoint: CGPoint = touch.locationInView(self.view)            if abs(currentPoint.x - self.firstLocation.x) >= 10 {//当手势有移动时,判断手势异动距离是否已经大于10个点,如果大于10个点即为非点击事件了                self.state = UIGestureRecognizerState.Failed            }        }    }        override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent) {        super.touchesEnded(touches, withEvent: event)        self.firstLocation = CGPointZero                self.state = UIGestureRecognizerState.Ended       //手势识别成功,将状态标记为识别成功    }        override func touchesCancelled(touches: Set<UITouch>, withEvent event: UIEvent) {        super.touchesCancelled(touches, withEvent: event)        self.firstLocation = CGPointZero    }}

         4、UIGestureRecognizer进阶
         4.1 UIGestureRecognizer状态说明

         此处借用一下苹果官方文档的图片,:)

        

         图片左半边是离散手势(如点击事件)的状态变迁图,右半边是连续事件(如滑动)状态变迁图。任何事件都是从Possible(可能的)的状态开始,经过必要的事件之后,转变成Failed(失败)、Canceled或Recognized(可识别)状态,即手势识别结束。

  • 离散事件缺少中间的Changed(正在变化的)中间状态,直接从事件的Began到结束状态Failed或Recognized
  • 连续事件中的Changed不停的标记当前正在发生的事件的状态,如滑动事件,会一直记录当前手势移动的位置,对应于代码中touchesMoved
  • 当手指离开屏幕,表示手势事件结束。此时需要识别结束后的事件是否满足既定的手势识别条件。如移动的距离和速度等是否满足要求,如果满足即表示识别成功(Recognized),否则表示识别失败(Failed);若中途遭遇其他系统事件中断(如内存不足),即表示手势识别事件被取消(Canceled)。

         4.2 多手势识别顺序问题

              前面我们已经简单提到过,同一个View可以包含多个手势,但是一个手势只能对应一个View。如果在同一个View中包含了多个手势,在iOS系统默认情况下,没有任何顺序可言,这就是通常所说的手势冲突问题。好在苹果允许我们修改手势的部分默认行为方式:

  • 两个具有部分包含关系的手势,可以通过指定识别顺序来解决手势冲突问题;
            如:panRecognizer.requireGestureRecognizerToFail(swipeRecognizer)

rotationGesture.requireGestureRecognizerToFail(panGesture)

  • 可以指定同时识别的两个手势
           这个需要实现手势代理方法gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:方法,在该方法中返回YES(true)即可
  • 指定两个手势之间的阻止关系,如手势A响应时,不响应手势B,但是手势B响应时,需要响应手势A

            panRecognizer.canPreventGestureRecognizer(pinchGestureRecognizer)            





0 0
原创粉丝点击