手势与UITouch的区别:
手势继承自UIGestureRecognizer-->NSObject。
而UITouch直接继承自NSObject。
事实上,手势和UITouch本身关系不大,在IOS3.2之前根本没有手势,以前的所有操作都依赖于UITouch,这也是为什么UITouch定义在UIRsponder中的原因之一,并且所有的UIResponder及其子类都自带监听UITouch的方法。
手势的分类:
一般来说,我们用到的UIGestureRecognizer的子类有以下几种:
1:UITapGestureRecognizer
这个手势也就是常见的点击手势,可以通过设置numberOfTapsRequired来设定需要连续多少次点击才会触发事件。
需要注意的是:
如果在一个view上面同时既要触发单击又要触发双击,这样的情况下直接将两个手势加在这个view上面会导致触发双击事件的时刻,单击事件也会被触发。我们需要设置这样一个属性,来让系统一次只触发双击或者单击事件。
[doubleTap requireGestureRecognizerToFail:tap];
这个方法也可以用于对其它手势的互斥。
numberOfTouchesRequired可以用来设置手势需要多少手指。
2: UIPinchGestureRecognizer放大缩放手势(放大过程中不断触发)。
需要注意的是,通过pinch.scale得到的数值是相对于原图的缩放比例,所以需要成员变量保存。
pinch.velocity可以得到手势的速率。
3:UIPanGestureRecognizer
拖动手势(拖动过程中不断触发)。
通过[pan translationInView:]返回一个CGpoint,这个Point的内容代表的就是当前鼠标相对于刚开始(按下的位置)的相对坐标。
通过[pan locationInView:self.view]可以得到当前鼠标相对于self.View的相对坐标。(同理可得到其它坐标系下坐标)
4:UILongPressGestureRecognizer
长按手势。
numberOfTapsRequired:长按之前需要先tap几下。
numberOfTouchesRequired:需要几个手指。
minimumPressDuration:最小持续长按时间。
注意:长按事件的监听不像点击事件一样只触发一次,也不像拖动事件一样会不断的触发,这个时间会被触发两次,分别是在长按生效的时刻触发一次,和松开手指的时刻触发一次。可以通过state,进行不同处理。5:UISwipeGestureRecognizer
轻滑手势,也就是cell中的滑动删除手势。
numberOfTouchesRequired需要几个手指。
@property(nonatomic)UISwipeGestureRecognizerDirection direction;
设置想要监听轻滑的方向。6:UIRotationGestureRecognizer
旋转手势(持续触发)。这个手势与pinch类似。两个属性rotation和velocity。
关于父类UIGestureRecognizer:
UIGestureRecognizer是所有手势的根类,所以,它的很多方法都是在手势中能够使用的。
首先是当前手势的状态:
UIGestureRecognizerState。
一般情况下,通过判断这个状态来区分手势在什么阶段。
@property(nonatomic,readonly)UIView *view;
所有手势都可以通过这个属性获得当前响应手势的view。
可以为所有手势再添加一个触发事件,当这个手势被触发的时刻,原有处理方法触发后马上出发这个方法。(也可以先用init初始化,再添加这个事件监听)。
addTarget:selfaction:@selector()
delaysTouchesBegan属性会将当前的手势级别提升,也就是说,优先响应这个手势,只有这个手势失败后才会触发其他手势。
delaysTouchesEnded同理,只有这个手势失败后,才结束整个手势识别过程。
- (CGPoint)locationInView:(UIView*)view; 所有手势其实都可以得到自己的坐标。
- (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(UIView*)view;某个手指的点击的位置(手势开始的时刻的位置))。
------------------如果需要对手势事件响应进行自定义就要用到代理了-------------------------
UIGestureRecognizerDelegate
这个代理包含三个回调方法。
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
UITouch:(包含点击次数和时间等属性。)
参考:http://justcoding.iteye.com/blog/1473287
UITouch的监听方法直接定义在UIResponder中
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
UIResponder:
利用这个类可以实现对touch事件的监听和对设备自身运动motion的监听。
还支持远程事件。
- (void)remoteControlReceivedWithEvent:(UIEvent *)event
参考文章:
http://blog.csdn.net/maojudong/article/details/7798138
关于firstResponder:(UIResponder默认为不能成为第一响应者的,子类覆写canBecomeFirstResponder方法来改变它)
3. 输入视图管理相关:
输入视图是指当对象为 firstResponder 对象时,需要借助另外一个视图用来处理当前对象的信息输入,如 UITextView 和 UITextField 两个对象,在 UITextField 成为 firstResponder 对象时,会显示一个系统键盘,用来输入信息。这个键盘视图就是一个输入视图了。一共有两个相关的输入视图,一个是 inputView, 另一个是 inputAccessoryView,这两个视图显示的关系如下图:
从图中可以看到, 如果 inputView 和 inputAccessoryView 两个属性都指定了相应的视图,则 inputAccessoryView 对象显示在 inputView 对象的上面。
与输入相关的还有一个 reloadInputViews 方法用来重新载入输入视图。
如何获取一个view所属的viewController:
通过superView是无法得到viewController的。
UIResponder* nextResponder = [view nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController*)nextResponder;
}
为何可以通过responder获取所属viewController而不是获得的父视图view这与ios中响应者链的事件传递顺序有关
-------
响应链的过程:
事实上,在内存中,所有继承自uiresponder的对象会依赖其层级关系形成一棵n叉数,而事件就是回溯传递的。所以如果一个view不是viewcontroller中的view,那么它的nextresponder一般就是它的父容器。