美文网首页
事件层级原理 响应链

事件层级原理 响应链

作者: 纳兰沫 | 来源:发表于2020-05-26 22:57 被阅读0次

iOS事件

运动事件,远程控制事件、触摸事件

image.png

触摸事件

事件传递的顺序

EOCLightGrayView *grayView = [[EOCLightGrayView alloc] initWithFrame:CGRectMake(50.f, 100.f, 260.f, 200.f)];
EOCRedView *redView = [[EOCRedView alloc] initWithFrame:CGRectMake(0.f, 0.f, 120.f, 100.f)];
EOCBlueView *blueView = [[EOCBlueView alloc] initWithFrame:CGRectMake(140.f, 100.f, 100.f, 100.f)];
EOCYellowView *yellowView = [[EOCYellowView alloc] initWithFrame:CGRectMake(50.f, 360.f, 200.f, 200.f)];
[self.view addSubview:grayView];
[grayView addSubview:redView];
[grayView addSubview:blueView];
[self.view addSubview:yellowView];
image.png

当点击红色的时候 打印为

2020-05-26 20:12:27.319652+0800 事件层次分析 [67838:232210] yellowColorView pointInside
2020-05-26 20:12:27.319911+0800 事件层次分析 [67838:232210] ligthGrayColorView pointInside
2020-05-26 20:12:27.320128+0800 事件层次分析 [67838:232210] blueColorView pointInside
2020-05-26 20:12:27.320301+0800 事件层次分析 [67838:232210] redColorView pointInside

事件传递的方法

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
  • hitTest方法会判断pointInside是不是在view里面 如果是的话 就进行遍历,同时返回真正事件相应的对象


    image.png
  • 当不在view里面的话 就返回nil


    image.png
  • 当点击的是自己的时候 就返回自己


    image.png
代码实现
案列
  • 按钮过小 扩大点击范围
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {

    NSLog(@"%s",__func__);
    //在我想要的区域,pointInside返回YES
    CGRect rect = self.bounds;
    
    if (rect.size.width < 50.f) {
        rect.origin.x -= (50.f - rect.size.width)/2;
    }
    
    if (rect.size.height < 50.f) {
        rect.origin.y -= (50.f - rect.size.width)/2;
    }
    
    rect.size.width = 50.f;
    rect.size.height = 50.f;
    
    if (CGRectContainsPoint(rect, point)) {
        return YES;
    }

    return [super pointInside:point withEvent:event];

}
  • 超出范围
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    
    NSArray *subviews = [[self.subviews reverseObjectEnumerator] allObjects];
    UIView *tmpView = nil;
    for (UIView *view in subviews) {
        CGPoint converedPoint = [self convertPoint:point toView:view];
        if ([view pointInside:converedPoint withEvent:event]) {
            tmpView = view;
            break;
        }
    }
    
    if (tmpView) {
        return tmpView;
    }else if ([self pointInside:point withEvent:event]){
        return self;
    }else{
        return nil;
    }
}

响应链

image.png
image.png

点击红色位置之后 响应链是从底部一层层的往上传递 如果上层有view 就传递给view 如果没有view 就传给ViewController

手势事件

  • 手势事件和hitTest pointInSide的关系
    1.当点击在手势的视图上时 响应了手势的点击事件
    image.png
    2.当hitTest返回nil的时候 没有响应手势的点击事件
    image.png

手势的响应的前提也是要先找到这个对象

touch事件是View本身就有的事件 手势事件是叠加在View上的事件

  • 当通过hitTest和pointInside找到了View 然后如果View或者他的superView有手势事件 都会响应
    image.png
    当在grayView上添加手势 点击红色区域或者蓝色区域的时候 都会响应手势
    image.png
  • 手势和View的touch事件的关系
    当手势响应之后 会取消掉View的touch事件
    image.png

可以通过
tapGesture.delaysTouchesBegan = NO; // 是否延迟View的touch事件的识别,如果为YES,阻止touch方法的识别 如果延迟了 手势也识别了的话 就放弃touch事件
tapGesture.cancelsTouchesInView = NO;// 识别手势之后 是否取消View的touch事件
来改变touch事件是否执行

button事件

  • button事件和hitTest pointInSide的关系

button的响应的前提也是要先找到这个对象

  • 通过button里面的四个touch的方法来判断是哪种button事件

多手势的共存和互斥

  • 多手势的共存
//手势支不支持touch
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    
    return YES;
    
}
//手势已经识别,通过这个方法的返回值,看是否响应
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    
    return YES;
}
//两个手势是否共存(一起响应),A手势和B手势,只要这两个手势有一个手势的这个代理方法返回的YES,那么就是共存
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

    return YES;

}

当这个方法返回YES的时候 就是多个手势都响应 只要有一个手势的类里面实现了这个方法 并且返回YES 那么他这个手势就跟其他手势是共存的 必须2个手势同时设置为NO 才不共存

  • 多手势的互斥
//互斥用的:gestureRecognizer它要响应,必须得满足otherGestureRecognizer响应失败,才可以,otherGestureRecognizer的优先级最高
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
}

//互斥用的:otherGestureRecognizer它要响应,需要gestureRecognizer响应失败,才可以,gestureRecognizer的优先级最高
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}
[手势2 requireGestureRecognizerToFail:手势1];

设置手势2必须在手势1响应失败的情况下 才能响应 以实现手势的互斥

tableview的cell的点击事件走的是touch事件

相关文章

网友评论

      本文标题:事件层级原理 响应链

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