iOS 设置button的点击范围(不在父视图部分支持点击的实现)

当我们把一个button放在一个View上,默认可点击范围是button的bounds且当超过父视图的部分点击是无响应的。
如图:A区域响应;B,C均不响应。

iOS 设置button的点击范围(不在父视图部分支持点击的实现)_第1张图片
image.png

当触摸屏幕,系统首先会把event放在事件队列中。
当event派发执行时,首先在当前视图层中寻找适合处理事该件的view。会调用一下两个方法。

- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;   // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;   // default returns YES if point is in bounds

第一个问题:点击C区域响应事件。
这个我们通过重写这个方法解决

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

判断如果point处在C区域返回YES即可解决;

第二个问题:超过父视图部分B点击响应

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    CGPoint hitPoint = [self convertPoint:point toView:self.btn];
    if ([self.btn pointInside:hitPoint withEvent:event]) {
        return self.btn;
    }else{
        return [super hitTest:point withEvent:event];
    }
}

其中self.btn为点击的button

最后写了个:UIButton+HitControl
使用就方便了 直接设置button的hitFrame
源码:

#import "UIButton+HitControl.h"
#import 
@implementation UIButton (HitControl)
-(void)setHitFrame:(CGRect)hitFrame{
    NSValue *hitValue = [NSValue valueWithCGRect:hitFrame];
    objc_setAssociatedObject(self, @selector(hitFrame), hitValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(CGRect)hitFrame{
    NSValue *hitValue = objc_getAssociatedObject(self, _cmd);
    return hitValue.CGRectValue;
}

-(void)setHitInset:(UIEdgeInsets)hitInset{
    NSValue *insetValue = [NSValue valueWithUIEdgeInsets:hitInset];
    objc_setAssociatedObject(self, @selector(hitInset), insetValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    self.hitFrame = UIEdgeInsetsInsetRect(self.bounds, hitInset);
}
-(UIEdgeInsets)hitInset{
    NSValue *insetValue = objc_getAssociatedObject(self, _cmd);
    return insetValue.UIEdgeInsetsValue;
}


-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    if (CGRectEqualToRect(self.hitFrame, CGRectZero)) {
        return [super pointInside:point withEvent:event];
    }
    return CGRectContainsPoint(self.hitFrame, point);
}
@end

demo:https://github.com/GitHubXuLiying/HitTesta

你可能感兴趣的:(iOS 设置button的点击范围(不在父视图部分支持点击的实现))