iOS 设置button的点击范围(不在父视图部分支持点击的实现
2017-11-24 本文已影响164人
为之则易ing
当我们把一个button放在一个View上,默认可点击范围是button的bounds且当超过父视图的部分点击是无响应的。
如图:A区域响应;B,C均不响应。
![](https://img.haomeiwen.com/i1362023/f4fa14274f276fe2.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点击响应(这个还没找到特别好的方法,有个low的方法)
1、自定义View放在button下面,如图下面红色View
![](https://img.haomeiwen.com/i1362023/20f6a4af09e8c6ed.png)
2、重写自定义View方法
-(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
如果想点击整个红色View都响应事件。可以重设button的可点击区域实现。
最后写了个:UIButton+HitControl
使用就方便了 直接设置button的hitFrame
源码:
#import "UIButton+HitControl.h"
#import <objc/runtime.h>
@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