响应链

来源:互联网 发布:费城实验是真的吗 知乎 编辑:程序博客网 时间:2024/05/22 07:54
  • 主要方法

  • 看窗口是否能接收。 如果不能 return nil; 使自己不能接收事件,也不能处理事件,而且也不能把事件传递给子控件。
  • 判断点在不在窗口上 如果点在窗口上,意味着窗口满足合适的view
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;   // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system            - 接收者的坐标系中递归调用-pointInside:withEvent:


* 判断点在不在方法调用者的坐标系上
* point:是方法调用者的坐标系上的点

- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;   // default returns YES if point is in bounds

找最合适的view
point是接收者坐标系上的点

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{    // 1.判断自己能否接收事件    if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;    // 2.判断点在不在当前控件上面    if (![self pointInside:point withEvent:event]) return nil;    // 3.去找有没有比自己更合适的view        // 从后往前遍历自己的子控件    int count = self.subviews.count;    for (int i = count - 1; i >= 0; i--) {        // 获取子控件        UIView *childView = self.subviews[i];        // 转换坐标系        // 把自己坐标系上的点转换成子控件做坐标系上的点        CGPoint childPoint = [self convertPoint:point toView:childView];        UIView *fitView = [childView hitTest:childPoint withEvent:event];        // 找到最合适的view        if (fitView) {            return fitView;        }    }    // 没有找到比自己更合适的view    return self;}

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{    // 把自己的点转换按钮的坐标系上的点    CGPoint buttonPoint = [self convertPoint:point toView:_button];    if ([_button pointInside:buttonPoint withEvent:event]) return nil; //使当前 view 不响应    return [super hitTest:point withEvent:event];}

既然 -hitTest:withEvent: 是递归调用 -pointInside:withEvent: 也可以只重写 -pointInside:withEvent:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{    // 把左边控件上的点转换为右边上边控件的点//    CGPoint buttonPoint = [self convertPoint:point toView:_button];    // 从右边这个view上的点转换为坐标上的点    CGPoint buttonPoint =[_button convertPoint:point fromView:self];    if ([_button pointInside:buttonPoint withEvent:event]) return NO;       //当点在 button 边界内时    return [super pointInside:point withEvent:event];}
0 0