UIGestureRecognizer手势
一:手势衍生类
在iPhone或iPad的开发中,除了用touchesBegan / touchesMoved / touchesEnded这组方法来控制使用者的手指触控外,也可以用UIGestureRecognizer的衍生类別来进行判断。用UIGestureRecognizer的好处在于有现成的手势,开发者不用自己计算手指移动轨迹。UIGestureRecognizer的衍生类別有以下几种:
UITapGestureRecognizer点一下
UIPinchGestureRecognizer二指往内或往外拨动
UIRotationGestureRecognizer旋转
UISwipeGestureRecognizer滑动,快速移动
UIPanGestureRecognizer拖移,慢速移动
UILongPressGestureRecognizer长按
這些手势別在使用上也很简单,只要在使用前定义并添加到对应的视图上即可。
二:手势的使用
首先要开启用户交互属性(只有此属性设为YES 添加的手势才会生效)
_imageView.userInteractionEnabled = YES;
然后给imageView添加点击手势
//UIGestureRecognizer 是所有手势的基类(父类)
//点击手势
//target- action 叫 目标-动作机制,(得益于oc的动态运行时机制,可以让任意target对象,执行任何aciton方法)
//将点击手势,添加到imageView上(默认为单击)
//设置点击次数 默认为2的时候为双击触发
tap.numberOfTapsRequired =1;
//需要多少个手指同时点击触发
tap.numberOfTouchesRequired =1;
[_imageView addGestureRecognizer:tap];
三:关联手势的处理
问题來了。有些手势其实是互相关联的,例如Tap与LongPress、Swipe与Pan,或是Tap一次与Tap兩次。当一個UIView同时添加兩个相关联的手势时,到底我这一下手指头按的要算是Tap还是LongPress?如果照預设作法来看,只要「先滿足条件」的就会跳出并呼叫对应方法,举例来说,如果同时注册了Pan和Swipe,只要手指头一移动就会触发Pan然后跳出,因而永远都不會发生Swipe;单点与双点的情形也是一样,永远都只会触发单点,不會有双点。
那么这个问题有解吗?答案是肯定的,UIGestureRecognizer有个方法叫做requireGestureRecognizerToFail,他可以指定某一个recognizer,即便自己已经滿足條件了,也不會立刻触发,会等到该指定的recognizer确定失败之后才触发。这是一种思想,一种优先确定不确定的事件,根据不确定事件的反馈去执行应该执行的事件。
//双击确定侦测失败才会触发单击
[singleTap requireGestureRecognizerToFail:doubleTap];
注意:一个手势只能关联一个view,一个view可以关联多个手势
四:
//将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
//将像素point从view中转换到当前视图中,返回在当前视图中的像素值
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;
//将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;
//将rect从view中转换到当前视图中,返回在当前视图中的rect
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;
例把UITableViewCell中的subview(btn)的frame转换到controllerA中
// controllerA中有一个UITableView, UITableView里有多行UITableVieCell,cell上放有一个button
//在controllerA中实现:
CGRect rc = [cell convertRect:cell.btn.frame toView:self.view];
//或
CGRect rc = [self.view convertRect:cell.btn.frame fromView:cell];
//此rc为btn在controllerA中的rect
//或当已知btn时:
CGRect rc = [btn.superview convertRect:btn.frame toView:self.view];
//或
CGRect rc = [self.view convertRect:btn.frame fromView:btn.superview];