UIView 事件向下传递

如图:

悬浮的三个按钮下方有一个可以点击的灰色区域,但是点击按钮之间的透明区域,

这三个按钮的contentView会响应这个点击事件,这时候需要让这个contentView不响应这个点击事件。

解决方法如下(将此方法增加到这个contentView类中即可):

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

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

这个方法就是用来查找最合适处理事件的方法,查看这个方法相关的描述,如下:

返回farthest descendent (最后一级子视图) ,在这个例子里面返回的也就是悬浮的按钮。

如果hitTest:withEvent:方法中返回nil,那么调用该方法的控件本身和其子控件都不是最合适的view,也就是在自己身上没有找到更合适的view。那么最合适的view就是该控件的父控件。就可以让这个contentView无视这个点击事件,也就将这个点击事件传了出去。

 

超出父视图区域变成可点击

- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; 

这个方法就是用来判断触摸点是否在其身上,返回一个BOOL值.  如果返回YES,代表点在方法调用者的坐标系上;返回NO代表点不在方法调用者的坐标系上,那么方法调用者也就不能处理事件。

在正常情况下,3区域是接收到点击事件的,这是因为  pointInside:withEvent 返回了NO, 如果我们想要让3区域可点击,就需要重写这个方法,判断如果点击区域在3的范围内,return YES;

 

我们可以假装模拟一下系统的调用过程:

我们可以重写- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event这个方法,自己来模仿父类是如何处理找到最合适的视图的。当然我们也可以调用父类的这个方法,这样重写就没什么作用了。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    
    NSLog(@"点击了%@",[super hitTest:point withEvent:event]);
    // 1.判断下自己能否接收事件
    if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
    
    // 2.判断下点在不在当前控件上
    if ([self pointInside:point withEvent:event] == NO) return  nil; // 点不在当前控件
    
    
    // 3.从后往前遍历自己的子控件
    // 1 0
    int count = (int)self.subviews.count;
    for (int i = count - 1; i >= 0; i--) {
        // 获取子控件
        UIView *childView = self.subviews[i];
        
        // 把当前坐标系上的点转换成子控件上的点
        CGPoint childP =  [self convertPoint:point toView:childView];
        
        UIView *fitView = [childView hitTest:childP withEvent:event];
        
        if (fitView) {
            return fitView;
        }
        
    }
    // 4.如果没有比自己合适的子控件,最合适的view就是自己
    return self;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值