
- Removed YuMi/Library/ (138 MB, not tracked) - Removed YuMi/Resources/ (23 MB, not tracked) - Removed old version assets (566 files, not tracked) - Excluded Pods/, xcuserdata/ and other build artifacts - Clean repository optimized for company server deployment
193 lines
7.2 KiB
Objective-C
193 lines
7.2 KiB
Objective-C
//
|
||
// 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
|