iOS UI高级之事件的分发

一、 事件的分发


1、当点击屏幕的时候iOS设备的硬件会检测(检测的原理可以去查找资料,好像触摸屏分为电容屏和电阻屏,然后根据一些他们的特性来检测的)到这个触摸事件,然后打包到UIEvent对象防盗应用程序的事件分发队列里面(队列:先进先出的特点,所有先进去的先执行)。UIApplication对象从队列里面取出最先进去的那个事件然后进行分发。一般会先传递给Window 。


解释下这两个方法:

方法1

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

方法2

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; 

当系统在调用第一个方法时会自动调用第二个方法,可以看出,第二个方法是判断point那个点是不是在调用第一个方法的视图上,如果是则方法1会返回当前这个视图,否则返回nil事件的处理是根据返回的视图来执行响应的处理方法的,等下讲解关于事件链的传递,现在先讲事件的分发。


来看看实例:UIWindow->myview->view1、view2

在window上面有一个子视图myview,在my view视图上有两个子视图view1,view2

假如说我们点击了view2视图


分析点击view2之后事件的分发流程:

在点击了view2之后 系统检测到这个事件,然后放在了事件的队列里面,当uiapplication对象取出事件的时候向window发送消息,此时会调用window里面的

(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 方法   (  编号:方法1)

在调用此方法的时候会在方法里面调用- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 方法  (编号: 方法2)


当方法2判断出point(触摸屏幕的手指的位置)这个点在window上面 ,则会向直接加载到window上的视图myiew发送消息,同时执行过程和上面一样。先调用方法1.同时在方法1里面调用方法2,检测到point那个点是在myview上,则会向所有的子视图也就是view1和view2发送消息,然后执行相同的操作。

注意:在向所有的子视图发送消息的时候会先给top层那个发送(每个视图上的子视图的存放都是放在数组里面的,先添加进去的下标小,后添加的大)。因为,假如有多个视图是重合在一起的情况,检测到的点肯定都是在这些重合的视图上的,但是返回那个视图呢?一般我们只处理顶层那个我们看的到到视图的响应,这个顶层点视图肯定是最后添加上去的,所有在向所有的子视图发送消息时会先发送给顶层那个,这样假如有重合的情况下 在重叠的下面视图就不必发送消息了,这样效率会高。 我们也可以自定义方法1 来返回指定的视图。

例如:在一个视图view上有一个button和一个scrollview重叠,button在下面,scrollview在顶层。我们触摸这个位置的时候方法1默认返回的是视图scrollview,但是我们可以自定义让它返回button视图

我们在view这个视图点implement里面重写方法1:

(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 

//事件拦截 如果view有这些条件限制 则返回nill

if (self.alpha < 0.01 || self.userInteractionEnabled == NO || self.hidden == YES) {

        return nil;

    }

//判读触摸点是不是在这个视图里面 如果是 则遍历子视图 button和scrollview 系统默认的是先向top层的发送消息,然后返回它,这里我们判断出这个点在重叠的区域的时候让它返回button

    if ([self pointInside:point withEvent:event]) {


NSArray *subViews = self.subviews;

        //从顶层开始遍历  因为如果有重叠的 情况 一般在下面层的 控件事件我们 不需要处理 只处理顶层那个

        for (NSInteger i = subViews.count - 1; i >= 0; i--) {

            UIView *view = subViews[i]; //第一次循环的时候 view = scrollview

// 将触摸点转化到scrollview 视图上

            CGPoint convertPoint = [self convertPoint:point toView:view];

//这句比较关键 在重叠的情况下 系统默认的返回时top层那个视图 这里也就是scrollview

            UIView *view1 = [view hitTest:convertPoint withEvent:event];

return view1;//系统估计在这里就直接返回top视图了 但是我们要返回的不是这个 因此下面我们改变返回的视图

            if (view1 != nil) {

                return subviews[i-1];//返回button

break;

            }


else

 return nill;


这里我们 的事件的分发就讲完了,实际上就是不断的查找,直到找到触摸的那个视图。


关于响应者链欢迎点击下一篇博客(由于篇幅的原因写在下一篇)








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

moxi_wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值