您好,欢迎来到伴沃教育。
搜索
您的当前位置:首页iOS UIView事件响应链机制

iOS UIView事件响应链机制

来源:伴沃教育

流程

  1. 点击一个UIView或产生一个触摸事件A,这个触摸事件A会被添加到由UIApplication管理的事件队列中(即,首先接收到事件的是UIApplication)。

  2. UIApplication会从事件对列中取出最前面的事件(此处假设为触摸事件A),把事件A传递给应用程序的主窗口(keyWindow)。

  3. 窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件。

看A,B两个效果图体会下这个流程

A:


B:


怎么找到合适的View流程

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (!self.isUserInteractionEnabled || self.isHidden || self.alpha <= 0.01) {
        return nil;
    }
    if ([self pointInside:point withEvent:event]) {
        for (UIView *subview in [self.subviews reverseObjectEnumerator]) {
            CGPoint convertedPoint = [subview convertPoint:point fromView:self];
            UIView *hitTestView = [subview hitTest:convertedPoint withEvent:event];
            if (hitTestView) {
                return hitTestView;
            }
        }
        return self;
    }
    return nil;
}

是否允许接收触摸事件

该hitTest:withEvent:方法首先检查是否允许视图接收触摸。如果出现以下情况,则允许视图接收触摸:

  1. 视图未隐藏:

self.hidden == NO

  1. 该视图启用了用户交互:

self.userInteractionEnabled == YES

  1. 视图的alpha级别大于0.01:

self.alpha > 0.01

  1. 该视图包含以下内容:

pointInside:withEvent: == YES

常见用法

  1. 比如上图这个按钮太小,我手指可能点击不到,不增加icon的大小情况下,增加额外的触摸。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (!self.isUserInteractionEnabled || self.isHidden || self.alpha <= 0.01) {
        return nil;
    }
    CGRect touchRect = CGRectInset(self.bounds, -10, -10);
    if (CGRectContainsPoint(touchRect, point)) {
        for (UIView *subview in [self.subviews reverseObjectEnumerator]) {
            CGPoint convertedPoint = [subview convertPoint:point fromView:self];
            UIView *hitTestView = [subview hitTest:convertedPoint withEvent:event];
            if (hitTestView) {
                return hitTestView;
            }
        }
        return self;
    }
    return nil;
}

2.比如把事件传递到被覆盖的下面的视图,重写覆盖视图的hitTest方法

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *hitTestView = [super hitTest:point withEvent:event];
    if (hitTestView == self) {
        hitTestView = nil;
    }
    return hitTestView;
}

3.将事件传递给子视图,如下图子视图占据大部分空间,一些手势在边缘地方也就是UIView里,也应该响应到UIScrollView中,重写UView方法。


- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *hitTestView = [super hitTest:point withEvent:event];
    if (hitTestView) {
        hitTestView = self.scrollView;
    }
    return hitTestView;
}

Copyright © 2019- bangwoyixia.com 版权所有 湘ICP备2023022004号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务