美文网首页知识点总结
iOS UI事件的传递机制

iOS UI事件的传递机制

作者: 飞不越疯人院 | 来源:发表于2019-04-04 10:51 被阅读4次

    日常开发中用到事件传递的场景:

    自定义的Tabbar的中间按钮为大的圆形; 预期效果是只让红框内的圆形部分相应点击事件;
    文章讲解内容代码示例

    image.png
    现在的效果是点击了非圆形区域也相应了事件,这明显不是想要的效果 image.png

    处理后的效果

    image.png

    事件传递的主要两个方法:

    ///最终哪个视图响应事件, 将哪个视图返回;
    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        if (self.hidden == YES || self.alpha < 0.01 || self.isUserInteractionEnabled == NO) {//0.01临界值
            return nil;
        }
        if ([self pointInside:point withEvent:event]) {
            __block UIView *view = nil;
            ///遍历当前视图的subviews
            [self.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                ///转换坐标
                CGPoint thePoint = [self convertPoint:point toView:obj];
                ///子视图调用
                view = [obj hitTest:thePoint withEvent:event];
                if (view) {
                    *stop = YES;
                }
            }];
            if (view != nil) {
                return view;
            }else {
                return self;
            }
        }else {
            ///点击区域不在当前视图范围内, 不要响应
            return  nil;
        }
    }
    
    ///判断某个点击位置是否在当前视图内;
    - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
        CGFloat x = point.x;
        CGFloat y = point.y;
        CGFloat centerX = self.center.x;
        CGFloat centerY = self.center.y;
        ///点击点与当前控件中心点距离
        double twoPointOffset = sqrt(pow((x - centerX), 2) + pow(y - centerY, 2));
        ///判断是否在圆形区域内
        if (twoPointOffset <= self.frame.size.width / 2) {
            return YES;
        }
        return NO;
    }
     
    


    事件的传递流程:

    知识点:倒序遍历, 因为不考虑透明度和frame的因素, 后面添加的会在最上层,理论上也是最先响应;

    视图响应流程:

    用到的几个方法
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    }
    - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    }
    - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    }
    

    如果点击了View5. 则处理事件流程为:


    知识点:如果到了UIApplicationDelegate这一层事件仍然没有被响应处理掉,会出现什么现象?
    注意, 程序不会崩溃, 而是会将这个事件丢弃掉;


    其他:UIView和Calyer的关系

    UIView CALayer
    可以响应事件 不能响应事件
    UIViewLayerdelegate --
    负责处理事件 负责绘制
    内部有subviews 内部有subLayers

    这种分工方式体现出单一职责原则
    某种程度上简单理解为:CALayer+响应链/事件 = UIView;

    相关文章

      网友评论

        本文标题:iOS UI事件的传递机制

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