首先介绍UITouch:
UITouch简介:
当用户用一根手指触摸屏幕时,会创建一个与手指相关联的UITouch对象,一根手指对应一个UITouch对象(UIView默认是只能有一个手指触摸 要想能接收多个手指的触摸 需要设置Multiple Touch.)
当手指移动时,系统会更新同一个UITouch对象,使之能够一直保存该手指的触摸位置。
当手指离开屏幕时,系统会销毁相应的UITouch对象
UITouch的两个重要方法 : (通过这两个方法获取当前触摸点和之前触摸点的坐标)
- (CGPoint)locationInView:(UIView*)view; 获取点的当前位置
返回值表示触摸在view上的位置,这里返回的位置是针对view的坐标系的(以view的左上角为原点(0, 0))
调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
- (CGPoint)previousLocationInView:(UIView *)view; 获取点的上一个位置
该方法记录了前一个触摸点的位置
触摸事件的产生和传递:
1.发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中
2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow)
3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,但是这仅仅是整个事件处理过程的第一步
4.找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理
touchesBegan…
touchesMoved…
touchedEnded…
如何找到一个最合适的视图(笼统): (如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件.)
1> 自己是否能接收触摸事件?若为否,直接返回nil.(直接返回nil表示包括该控件自己及其子控件都不处理这个触摸事件.)
注:UIView不接收触摸事件的三种情况: 1.不接收用户交互userInteractionEnabled = NO 2. 隐藏 hidden= YES 3. 透明 alpha = 0.0 ~0.01
2> 触摸点是否在自己身上?若为否,直接返回nil.
3> 前面两个条件若都满足, 从后往前遍历子控件,重复前面的两个步骤.
4> 如果没有符合条件的子控件,那么就返回self,表示自己最适合处理.
如何找到一个最合适的视图(详细):
先介绍两个在触摸过程中会调用的方法:
1. - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; 上面笼统的四步就是通过调用这个方法来执行的.
2. - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; 帮助第一个方法来判断触摸点是否在自己身上. 注意: 其中的point必须是基于本控件的坐标系!!!!
现在正式开始介绍(UIView *)hitTest:(CGPoint)pointwithEvent:(UIEvent *)event方法的具体实现:
1.判断自己是否能被触摸 :
if (self.userInteractionEnabled== NO || self.hidden == YES || self.alpha <= 0.01) return nil;
2.判断点在不在当前控件上面:
if (![selfpointInside:point withEvent:event]) return nil;
3. 从后往前遍历子控件,遍历的过程中调用它们的hitTest: withEvent: 的方法. 注意: 传入point的之前,需要将point转换为基于子控件的坐标系(注意:不是子控件所在的坐标系): CGPoint childPoint = [self convertPoint:point toView:childView];
一旦有一个子控件返回的UIView不为空 则返回它返回的view ,因为它就是我们要找得最合适的视图!
4.在第三步中没有找到比自己更合适的子view,那么返回自己即可, 自己即是最合适的视图
介绍完了机制 来几个题目:
1. 如何屏蔽一个控件的所有子控件的触摸事件?
重写该控件的 hitTest 方法 ,然后判断一下是否能被触摸,且点是否在自己身上,如果都没有问题 不遍历子控件 直接返回自己.(表示本控件就是最合适的视图)
2. 如果一个控件覆盖在button的上面, 如何做到 当点击在这个button上面的时候 能够让button处理到触摸事件?
重写该控件的hitTest 方法, 首先判断点是否在button上面(判断之前,记得把point转化为基于button的坐标系). 若在,那么直接返回这个button(表示button就是最合适的视图)