Files
yinmeng-ios/xplan-ios/Base/UI/UIButton/UIButton+EnlargeTouchArea.m
2023-08-29 17:54:23 +08:00

193 lines
7.4 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// UIButton+EnlargeTouchArea.m
// XCCategrayKit
//
// Created by Macx on 2018/8/30.
// Copyright © 2018年 KevinWang. All rights reserved.
//
#import "UIButton+EnlargeTouchArea.h"
#import <objc/runtime.h>
#define defaultInterval 0.0003 //默认时间间隔,不能太长,以免影响系统拍照等功能
@interface UIButton ()
/**
* bool YES 忽略点击事件 NO 允许点击事件
*/
@property (nonatomic, assign) BOOL isIgnoreEvent;
@end
@implementation UIButton (EnlargeTouchArea)
static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
static const char *UIControl_enventIsIgnoreEvent = "UIControl_enventIsIgnoreEvent";
//定义常量 必须是C语言字符串
static const char *imageFrameStr = "imageFrame";
static const char *titleFrameStr = "titleFrame";
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method newImageMethod = class_getInstanceMethod(self, @selector(new_imageRectForContentRect:));
Method oldImageMethod = class_getInstanceMethod(self, @selector(imageRectForContentRect:));
method_exchangeImplementations(newImageMethod, oldImageMethod);
Method newTitleMethod = class_getInstanceMethod(self, @selector(new_titleRectForContentRect:));
Method oldTitleMethod = class_getInstanceMethod(self, @selector(titleRectForContentRect:));
method_exchangeImplementations(newTitleMethod, oldTitleMethod);
//根据selector查找Method
SEL selA = @selector(sendAction:to:forEvent:);
SEL selB = @selector(new_sendAction:to:forEvent:);
Method methodA = class_getInstanceMethod(self,selA);
Method methodB = class_getInstanceMethod(self, selB);
//添加自定义方法
BOOL isAdd = class_addMethod(self, selA, method_getImplementation(methodB), method_getTypeEncoding(methodB));
if (isAdd) {//添加成功->替换
class_replaceMethod(self, selB, method_getImplementation(methodA), method_getTypeEncoding(methodA));
}else{//添加不成功->交换
//添加失败了 说明本类中有methodB的实现此时只需要将methodA和methodB的IMP互换一下即可。
method_exchangeImplementations(methodA, methodB);
}
});
}
- (void)new_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
self.yn_acceptEventInterval = self.yn_acceptEventInterval == 0 ? defaultInterval : self.yn_acceptEventInterval;
if (self.isIgnoreEvent){//默认可以响应点击事件
return;
}
if (self.yn_acceptEventInterval > 0){//第一次点击设定eventTimeInterval后可以响应点击事件
[self performSelector:@selector(setNoIgnoreEvent) withObject:nil afterDelay:self.yn_acceptEventInterval];
}
self.isIgnoreEvent = YES;//设置不可以响应点击事件
[self new_sendAction:action to:target forEvent:event];
}
// runtime 动态绑定 属性
- (BOOL)isIgnoreEvent{
return [objc_getAssociatedObject(self, UIControl_enventIsIgnoreEvent) boolValue];
}
-(void)setNoIgnoreEvent{
self.isIgnoreEvent = NO;
}
- (void)setIsIgnoreEvent:(BOOL)isIgnoreEvent {
objc_setAssociatedObject(self, UIControl_enventIsIgnoreEvent, @(isIgnoreEvent), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(void)setYn_acceptEventInterval:(NSTimeInterval)yn_acceptEventInterval{
objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(yn_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSTimeInterval)yn_acceptEventInterval{
return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}
- (void)setImageFrame:(NSValue *)imageFrame{
objc_setAssociatedObject(self, imageFrameStr, imageFrame, OBJC_ASSOCIATION_RETAIN);
}
- (NSValue *)imageFrame{
return objc_getAssociatedObject(self, imageFrameStr);
}
- (void)setTitleFrame:(NSValue *)titleFrame{
objc_setAssociatedObject(self, titleFrameStr, titleFrame, OBJC_ASSOCIATION_RETAIN);
}
- (NSValue *)titleFrame{
return objc_getAssociatedObject(self, titleFrameStr);
}
- (CGRect)new_imageRectForContentRect:(CGRect)contentRect{
if (CGRectEqualToRect(self.imageFrame.CGRectValue, CGRectZero)) {
return [self new_imageRectForContentRect:contentRect];
}
return self.imageFrame.CGRectValue;
}
- (CGRect)new_titleRectForContentRect:(CGRect)contentRect{
if (CGRectEqualToRect(self.titleFrame.CGRectValue, CGRectZero)) {
return [self new_titleRectForContentRect:contentRect];
}
return self.titleFrame.CGRectValue;
}
static char topNameKey;
static char rightNameKey;
static char bottomNameKey;
static char leftNameKey;
- (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);
}
- (void)enlargeTouchArea:(UIEdgeInsets)insets
{
[self setEnlargeEdgeWithTop:insets.top
right:insets.right
bottom:insets.bottom
left:insets.left];
}
- (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;
}
}
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
if(self.hidden) return nil;
CGRect rect = [self enlargedRect];
if (CGRectEqualToRect(rect, self.bounds))
{
return [super hitTest:point withEvent:event];
}
return CGRectContainsPoint(rect, point) ? self : nil;
}
+(UIButton *)buttonInitWithText:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor image:(UIImage *)image bgImage:(UIImage *)bgImage{
UIButton *button = [[UIButton alloc]initWithFrame:CGRectZero];
if(text.length > 0){
[button setTitle:text forState:UIControlStateNormal];
}
if(font != nil){
button.titleLabel.font = font;
}
if(textColor != nil){
[button setTitleColor:textColor forState:UIControlStateNormal];
}
if (image != nil){
[button setImage:image forState:UIControlStateNormal];
}
if(bgImage != nil){
[button setBackgroundImage:bgImage forState:UIControlStateNormal];
}
return button;
}
@end