有时候会遇到按钮本身较小,不好点击的情况。这个时候可能不方便扩大按钮,就可以使用这个方法来扩大点击范围但是不需要扩大按钮本身。
原理
利用了UIButton点击响应原理,UIButton在点击后,会调用hittest方法,来检查点击是否在范围内,如果不在则交给父view继续hittest。这个方法就是利用重写了hittest方法,来扩大点击范围。
实现
创建一个UIButton的category。定义一个方法,传入上,左,下,右四个参数。每个参数代表每个方向上扩大的距离。
#import <UIKit/UIKit.h>
@interface UIButton (Enlarge)
- (void)setTouchRangeWithTop:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right;
@end
因为category无法增加属性,就利用runtime来给UIButton添加四个属性。
定义四个属性的key。
char topKey;
char leftKey;
char bottomKey;
char rightKey;
实现.h定义的方法,给四个属性赋值
- (void)setTouchRangeWithTop:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right {
objc_setAssociatedObject(self, &topKey, @(top), OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &leftKey, @(left), OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &bottomKey, @(bottom), OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &rightKey, @(right), OBJC_ASSOCIATION_COPY_NONATOMIC);
}
重写hittest方法,如果点击的位置在扩大之后的范围内,就直接返回,否则就还是交给父类处理。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
CGFloat topNum = [objc_getAssociatedObject(self, &topKey) floatValue];
CGFloat leftNum = [objc_getAssociatedObject(self, &leftKey) floatValue];
CGFloat bottomNum = [objc_getAssociatedObject(self, &bottomKey) floatValue];
CGFloat rightNum = [objc_getAssociatedObject(self, &rightKey) floatValue];
CGRect range = CGRectMake(self.bounds.origin.x - leftNum, self.bounds.origin.y - topNum, self.bounds.size.width + leftNum + rightNum, self.bounds.size.height + topNum + bottomNum);
if (CGRectContainsPoint(range, point)) {
return self;
}else {
return [super hitTest:point withEvent:event];
}
}
调用
传入上左下右需要扩大的距离。
[self.testButton setTouchRangeWithTop:100 left:100 bottom:100 right:100];
如果为负数则是缩小点击范围。
总结
需要注意的是,扩大的范围不能超过父View的范围,超过了父View的范围点击就不能生效了。