扩大点击范围:
1、在 button 上添加一个view 增加点击事件
2、继承UIButton,实现如下效果:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
CGRect bounds = self.bounds;
//扩大原热区直径至26,可以暴露个接口,用来设置需要扩大的半径。
CGFloat widthDelta = MAX(26, 0);
CGFloat heightDelta = MAX(26, 0);
bounds = CGRectInset(bounds, -0.5 * widthDelta, -0.5 * heightDelta);
return CGRectContainsPoint(bounds, point);
}
3、在这个 Button 的 superview 里,重写 hitTest: 方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
CGRect rectBig = CGRectInset(self.bounds, -(27.0/2), -(27.0/2));
if (CGRectContainsPoint(rectBig, point)) {
return button;
}
return [super hitTest:point withEvent:event];
}
点击区域规定在圆形范围
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
[super hitTest:point withEvent:event];
CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
// 当然这个半径也可以扩大
CGFloat raidus = self.frame.size.height >= self.frame.size.width ? self.frame.size.width/2 :self.frame.size.width/2;
// 传入中心点 实时点击点 与半径判断 点击点是否在半径区域内
BOOL pointInRound = [self touchPointInsideCircle:center radius:raidus targetPoint:point];
if (pointInRound) {
return self;
} else {
return nil;
}
}
// 用来判断 圆形点击区域
- (BOOL)touchPointInsideCircle:(CGPoint)center radius:(CGFloat)radius targetPoint:(CGPoint)point {
CGFloat dist = sqrtf((point.x - center.x) * (point.x - center.x) + (point.y - center.y) * (point.y - center.y));
return (dist <= radius);
}
4、UIButton 分类
@interface UIButton (EnlargeEdge)
/** 设置可点击范围到按钮边缘的距离 */
- (void)setEnlargeEdge:(CGFloat)size;
/** 设置可点击范围到按钮上、右、下、左的距离 */
- (void)setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left;
@end
#import "UIButton+EnlargeEdge.h"
#import <objc/runtime.h>
static char topNameKey;
static char rightNameKey;
static char bottomNameKey;
static char leftNameKey;
@implementation UIButton (EnlargeEdge)
- (void)setEnlargeEdge:(CGFloat)size {
objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (void)setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left {
objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:bottom], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CGRect)enlargedRect {
NSNumber * topEdge = objc_getAssociatedObject(self, &topNameKey);
NSNumber * rightEdge = objc_getAssociatedObject(self, &rightNameKey);
NSNumber * bottomEdge = objc_getAssociatedObject(self, &bottomNameKey);
NSNumber * leftEdge = objc_getAssociatedObject(self, &leftNameKey);
if (topEdge && rightEdge && bottomEdge && leftEdge) {
return CGRectMake(self.bounds.origin.x - leftEdge.floatValue,
self.bounds.origin.y - topEdge.floatValue,
self.bounds.size.width + leftEdge.floatValue + rightEdge.floatValue,
self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue);
} else {
return self.bounds;
}
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
CGRect rect = [self enlargedRect];
if (CGRectEqualToRect(rect, self.bounds)) {
return [super pointInside:point withEvent:event];
}
return CGRectContainsPoint(rect, point) ? YES : NO;
}
@end
增加UIButton点击间隔:
#import <UIKit/UIKit.h>
@interface UIControl (FMGControl)
@property (assign, nonatomic) NSTimeInterval acceptEventInterval;
@end
#import "UIControl+FMGControl.h"
#import <objc/runtime.h>
static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
@implementation UIControl (FMGControl)
- (NSTimeInterval)acceptEventInterval {
return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}
- (void)setAcceptEventInterval:(NSTimeInterval)acceptEventInterval {
objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)FMG_ignoreEvent {
return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}
+ (void)load {
Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
Method b = class_getInstanceMethod(self, @selector(FMG_sendAction:to:froEvent:));
method_exchangeImplementations(a, b);
}
- (void)FMG_sendAction:(SEL)action to:(id)target froEvent:(UIEvent *)event {
if (self.acceptEventInterval > 0) {
if (self.userInteractionEnabled) {
[self FMG_sendAction:action to:target froEvent:event];
}
self.userInteractionEnabled = NO;
[self performSelector:@selector(setUserInteractionEnabled:) withObject:@(YES) afterDelay:self.acceptEventInterval];
// GCD 延迟执行 self.acceptEventInterval:为延迟时间
__weak typeof (self) weakSelf = self;
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.acceptEventInterval * NSEC_PER_SEC));
dispatch_after(delayTime, dispatch_get_main_queue(), ^{
weakSelf.userInteractionEnabled = YES;
});
} else {
[self FMG_sendAction:action to:target froEvent:event];
}
}
@end