一、前言
iPhone中处理触摸屏的操作,在3.2之前是主要使用的是由UIResponder而来的如下4种方式:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
但是这种方式甄别不同的手势操作实在是麻烦,需要你自己计算做不同的手势分辨。后来苹果就给出了一个比较简便的方式,就是使用UIGestureRecognizer。
二、UIGestureRecognizer
UIGestureRecognizer基类是一个抽象类,我们主要是使用它的子类(名字包含链接,可以点击跳到ios Developer library,看官方文档):
- UITapGestureRecognizer
- UIPinchGestureRecognizer
- UIRotationGestureRecognizer
- UISwipeGestureRecognizer
- UIPanGestureRecognizer
- UILongPressGestureRecognizer
从名字上我们就能知道Tap(点击)、Pinch(捏合)、Rotation(旋转)、Swipe(滑动,快速移动,是用于监测滑动的方向的)、Pan (拖移,慢速移动,是用于监测偏移的量的)以及 LongPress(长按)。
三、上代码才是硬道理
import UIKit
class ViewController: UIViewController {
@IBOutlet var im: UIImageView!
var lastScaleFactor : CGFloat! = 1 //放大、缩小
var netRotation : CGFloat = 0;//旋转
var netTranslation : CGPoint = CGPoint(x: 0, y: 0)//平移
var images : NSArray = ["1","2","3"]// 图片数组
var imageIndex : Int = 0 //数组下标
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: "handleTapGesture:")
//设置手势点击数,双击:点2下
tapGesture.numberOfTapsRequired = 2
self.view.addGestureRecognizer(tapGesture)
//手势为捏的姿势:按住option按钮配合鼠标来做这个动作在虚拟器上
let pinchGesture = UIPinchGestureRecognizer(target: self, action: "handlePinchGesture:")
self.view.addGestureRecognizer(pinchGesture)
//旋转手势:按住option按钮配合鼠标来做这个动作在虚拟器上
let rotateGesture = UIRotationGestureRecognizer(target: self, action: "handleRotateGesture:")
self.view.addGestureRecognizer(rotateGesture)
//拖手势 同一对象加入托手势时,滑动手势不能用。
let panGesture = UIPanGestureRecognizer(target: self, action: "handlePanGesture:")
self.view.addGestureRecognizer(panGesture)
//划动手势
//右划
let swipeGesture = UISwipeGestureRecognizer(target: self, action: "handleSwipeGesture:")
self.view.addGestureRecognizer(swipeGesture)
//左划
let swipeLeftGesture = UISwipeGestureRecognizer(target: self, action: "handleSwipeGesture:")
swipeLeftGesture.direction = UISwipeGestureRecognizerDirection.Left //不设置是右
self.view.addGestureRecognizer(swipeLeftGesture)
//长按手势
let longpressGesutre = UILongPressGestureRecognizer(target: self, action: "handleLongpressGesture:")
//长按时间为1秒
longpressGesutre.minimumPressDuration = 1
//允许15秒运动
longpressGesutre.allowableMovement = 15
//所需触摸手指个数
longpressGesutre.numberOfTouchesRequired = 2
self.view.addGestureRecognizer(longpressGesutre)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//双击屏幕时会调用此方法,放大和缩小图片
func handleTapGesture(sender: UITapGestureRecognizer){
//判断imageView的内容模式是否是UIViewContentModeScaleAspectFit,该模式是原比例,按照图片原时比例显示大小
if im.contentMode == UIViewContentMode.ScaleAspectFit{
//把imageView模式改成UIViewContentModeCenter,按照图片原先的大小显示中心的一部分在imageView
im.contentMode = UIViewContentMode.Center
}else{
im.contentMode = UIViewContentMode.ScaleAspectFit
}
}
//捏的手势,使图片放大和缩小,捏的动作是一个连续的动作
func handlePinchGesture(sender: UIPinchGestureRecognizer){
let factor = sender.scale
if sender.state == .Began{
print(factor)
}
if sender.state == .Changed{
print(factor)
}
im.transform = CGAffineTransformMakeScale(lastScaleFactor*factor, lastScaleFactor*factor)
//状态是否结束,如果结束保存数据
if sender.state == UIGestureRecognizerState.Ended{
lastScaleFactor = lastScaleFactor * factor
}
}
//旋转手势
func handleRotateGesture(sender: UIRotationGestureRecognizer){
//浮点类型,得到sender的旋转度数
let rotation : CGFloat = sender.rotation
if sender.state == .Changed{
print(rotation)
}
//旋转角度CGAffineTransformMakeRotation,改变图像角度
im.transform = CGAffineTransformMakeRotation(rotation+netRotation)
//状态结束,保存数据
if sender.state == UIGestureRecognizerState.Ended{
netRotation += rotation
}
}
//拖手势
func handlePanGesture(sender: UIPanGestureRecognizer){
//得到拖的过程中的xy坐标
let translation : CGPoint = sender.translationInView(im)
//平移图片CGAffineTransformMakeTranslation
im.transform = CGAffineTransformMakeTranslation(netTranslation.x+translation.x, netTranslation.y+translation.y)
if sender.state == UIGestureRecognizerState.Ended{
netTranslation.x += translation.x
netTranslation.y += translation.y
}
}
//划动手势
func handleSwipeGesture(sender: UISwipeGestureRecognizer){
//划动的方向
let direction = sender.direction
//判断是上下左右
switch (direction){
case UISwipeGestureRecognizerDirection.Left:
print("Left")
imageIndex++;//下标++
break
case UISwipeGestureRecognizerDirection.Right:
print("Right")
imageIndex--;//下标--
break
case UISwipeGestureRecognizerDirection.Up:
print("Up")
break
case UISwipeGestureRecognizerDirection.Down:
print("Down")
break
default:
break;
}
//得到不越界不<0的下标
imageIndex = imageIndex < 0 ? images.count-1:imageIndex%images.count
//imageView显示图片
im.image = UIImage(named: images[imageIndex] as! String)
}
//长按手势
func handleLongpressGesture(sender : UILongPressGestureRecognizer){
if sender.state == UIGestureRecognizerState.Began{
//创建警告
let alertV = UIAlertController(title: "长按", message: "开始了", preferredStyle: UIAlertControllerStyle.Alert)
let alertA = UIAlertAction(title: "OK", style: .Destructive, handler: nil)
alertV.addAction(alertA)
self.presentViewController(alertV, animated: true, completion: nil)
}
}
}
四、很多时候设置代理很重要
gestureRecognizerShouldBegin:
此方法在gesture recognizer视图转出UIGestureRecognizerStatePossible状态时调用,如果返回NO,则转换到UIGestureRecognizerStateFailed;如果返回YES,则继续识别触摸序列.(默认情况下为YES)gestureRecognizer:shouldReceiveTouch:
此方法在window对象在有触摸事件发生时,调用gesture recognizer的touchesBegan:withEvent:方法之前调用,如果返回NO,则gesture recognizer不会看到此触摸事件。(默认情况下为YES).gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
此方法如果返回YES,则两个gesture recognizers可同时识别,如果返回NO,则并不保证两个gesture recognizers必不能同时识别,因为另外一个gesture recognizer的此方法可能返回YES。也就是说两个gesture recognizers的delegate方法只要任意一个返回YES,则这两个就可以同时识别;只有两个都返回NO的时候,才是互斥的。默认情况下是返回NO。gestureRecognizer:shouldRequireFailureOfGestureRecognizer:
此方法可以根据要求设置屏障gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:
此方法可以根据要求设置屏障A requireGestureRecognizerToFail:B
此函数,它可以指定当A手势发生时,即便A已经滿足条件了,也不会立刻触发,会等到指定的手势B确定失败之后才触发。