首页 > 代码库 > iOS手势处理
iOS手势处理
iOS手势有着如下几种:
- UITapGestureRecognizer
- UIPinchGestureRecognizer
- UIRotationGestureRecognizer
- UISwipeGestureRecognizer
- UIPanGestureRecognizer
- UILongPressGestureRecognizer
上面的手势对应的操作是:
- Tap (点一下)
- Pinch (二指往內或往外拨动,平时经常用到的缩放) 矩阵变换
- Rotation (旋转) 矩阵变换
- Swipe (滑动,快速移动)
- Pan (拖移,慢速移动) 矩阵变换
- LongPress (长按)
注意:以下示例均把手势封装进一个View当中
UITapGestureRecognizer - 点击手势
GestureView.h + GestureView.m
- (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
Attaching a gesture recognizer to a view defines the scope of the represented gesture, causing it to receive touches hit-tested to that view and all of its subviews. The view establishes a strong reference to the gesture recognizer.
将手势识别器附着在一个view上,实际上定义了一个手势接收的区域,会将接收到的触摸事件传递给这个view以及这个view的所有的subviews.这个view会对这个手势识别器强引用.
可以总结两点:
1. 手势会传递给这个view中所有的subviews
2. view会强引用手势识别器
使用如下:
点击手势有两个参数可以设置:
numberOfTapsRequired 点击几次触发事件(默认是1)
numberOfTouchesRequired 需要几个手指点击(默认是1)
UIPinchGestureRecognizer - 缩放
GestureView.h + GestureView.m
缩放手势会用到矩阵变换.
UIRotationGestureRecognizer - 旋转
GestureView.h + GestureView.m
UISwipeGestureRecognizer - 滑动
GestureView.h + GestureView.m
UIPanGestureRecognizer - 平移
GestureView.h + GestureView.m
UILongPressGestureRecognizer - 长按手势
GestureView.h + GestureView.m
问题:如何处理一个view中添加了两个手势,1个是单击的手势,一个是双击的手势呢?
可以使用这个方法requireGestureRecognizerToFail:
实际上,这种方式会有延时感-_-!!!!
问题:如何将长按手势和拖拽手势合并在一起呢?
我们需要用代理实现,实现以下的方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
Asks the delegate if two gesture recognizers should be allowed to recognize gestures simultaneously.
询问这个代理,是否允许两个手势同时触发.
根据手势状态来识别手势触发事件的全称细节是十分重要的.
问题:如何让一个view的部分区域响应拖拽事件呢?
比方说,我们只需要下面红色线指定的区域响应拖拽事件:
要实现那个效果,以下方法是核心方法,配合手势的状态使用:
// 获取到当前手势在当前视图坐标中触摸的点
CGPoint point = [sender locationInView:self];
问题:如何在ViewController中获取到点击的坐标,让一个view跟随触摸点移动呢?
可以使用这几个最原始的处理触摸事件的方法来达到效果.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
也可以直接使用拖拽手势来实现的,不过不完美
他们两者的对比关系:
手势处理中核心的地方:
1. UIGestureRecognizerState非常重要,触发事件时可以直接根据这个状态值来判断事件的发生顺序
2. 处理多手势冲突时,可以使用依赖requireGestureRecognizerToFail:来处理,但效果不好
3. 处理多个手势并发响应的时候,需要实现代理并执行方法,请参考上面的事例
4. 仅仅处理一个view上局部的手势事件,需要用到手势的locationInView:方法,并与UIGestureRecognizerState状态值配合使用
附录:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
这是手势的代理方法,在可以不移除手势的情况下关闭手势的响应,此方法涉及到响应链.