美文网首页
事件传递和响应过程

事件传递和响应过程

作者: kim_xx | 来源:发表于2019-02-18 10:15 被阅读8次

    什么是事件传递

    事件传递:在iOS系统中,事件可以分为三类:

    public enum EventType : Int {
    
            
            case touches // 触摸事件
    
            case motion // 运动事件(比如重力感应、摇一摇等等)
    
            case remoteControl // 远程控制事件(比如可以用耳机控制手机)
    
            @available(iOS 9.0, *)
            case presses 
        }
    

    touch events 大多数都是相同的,并且在触摸事件发生的时候会传递给view;
    motion events 由UIKit触发,并且会由Core Motion framework区分motion events;
    Rmote-control events 允许响应对象接收来自 external accessory 或者 headset 的命令,这样就可以管理音频和视频了;
    Press events 表示 a game controller 和 AppleTV 或者 其他有物理按键的设备的远程事件之间的交互

    事件的传递过程:主要针对的是touch events

    当我们触摸屏幕的时候,为我们找到最合适的view。
    每当手机触摸屏幕,操作系统会把事件传递给当前的APP,在UIApplication接收到手指的事件之后,就会去调用 UIWindow 的 hitTest:withEvent: 方法,看看当前点击的点是不是在window内,如果是则继续调用其subview的 hitTest:withEvent: 方法,直到找到最后需要的view。

    hitTest:withEvent: 的内部实现

    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        if (self.hidden || self.userInteractionEnabled == NO || self.alpha < 0.01 || [self pointInside:point withEvent:event]) {
            return nil;
        }
        for (UIView *subView in self.subviews.reverseObjectEnumerator) {
            UIView *hitView = [subView hitTest:[subView convertPoint:point fromView:self] withEvent:event];
            if (hitView) {
                return hitView;
            }
        }
        return self;
    }
    

    什么是响应过程

    在事件传递过程中,找到事件响应的view,控件调用 touch 的一系列方法,判断是否实现 touch 的一系列方法,如果没有实现,就将事件传递给上一个响应者,如果最终找不到,方法作废

    - (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;
    

    如果有实现就由此View来响应,如果没有实现,那么就传递给他的下一个响应者。

    我的理解:


    在开发中的应用

    1.拦截点击事件

    重写父视图的 hitTest:withEvent: 方法

    2.扩大点击面积

    // 方法一
    - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
        CGRect rect = self.bounds;
        rect = CGRectInset(rect, -30, -30); // 增加点击面积
        return CGRectContainsPoint(rect, point);
    }
    
    // 方法二
    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        CGRect rect = self.bounds;
        rect = CGRectInset(rect, -30, -30); // 增加点击面积
        if (CGRectContainsPoint(rect, point)) {
            return self;
        }
        return nil;
    }
    

    相关文章

      网友评论

          本文标题:事件传递和响应过程

          本文链接:https://www.haomeiwen.com/subject/ligoeqtx.html