UIButton 扩展,利用runtime绑定block点击,图片文字展示方式,扩大点击事件

前言

之前都用的继承的方式实现扩大点击事件,绑定block,最好还是扩展为UIButton的分类,特意整理一下。

效果图:
button扩展.gif

代码

.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
typedef NS_ENUM(NSUInteger, LXButtonEdgeInsetsStyle) {
LXButtonEdgeInsetsStyleTop, // image在上,label在下
LXButtonEdgeInsetsStyleLeft, // image在左,label在右
LXButtonEdgeInsetsStyleBottom, // image在下,label在上
LXButtonEdgeInsetsStyleRight // image在右,label在左
};
#define Font(f) [UIFont systemFontOfSize:(f)]
typedef void (^ButtonBlock)(UIButton *button);
@interface UIButton (LXExpandBtn)
@property(nonatomic,strong)NSString *buttonId;//标识
@property(nonatomic,copy)ButtonBlock block;//添加点击事件
@property (nonatomic,assign) UIEdgeInsets hitTestEdgeInsets;//点击区域,默认为(0,0,0,0); 负的为扩大
//frame初始化
+(UIButton *)LXButtonWithTitle:(NSString *)title titleFont:(UIFont *)titleLabelFont Image:(UIImage *)image backgroundImage:(UIImage *)backgroundImage backgroundColor:(UIColor *)backgroundColor titleColor:(UIColor *)titleLabelColor frame:(CGRect)frame;
//约束初始化
+(UIButton *)LXButtonNoFrameWithTitle:(NSString *)title titleFont:(UIFont *)titleLabelFont Image:(UIImage *)image backgroundImage:(UIImage *)backgroundImage backgroundColor:(UIColor *)backgroundColor titleColor:(UIColor *)titleLabelColor;
//添加block
-(void)addClickBlock:(ButtonBlock)block;
/**
* 设置button的titleLabel和imageView的布局样式,及间距
*
* @param style titleLabel和imageView的布局样式
* @param space titleLabel和imageView的间距
*/
- (void)layoutButtonWithEdgeInsetsStyle:(LXButtonEdgeInsetsStyle)style
imageTitleSpace:(CGFloat)space;

.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#import "UIButton+LXExpandBtn.h"
#import <objc/runtime.h>
static const NSString *KEY_ButtonId = @"buttonId";
static const NSString *KEY_ButtonBlock = @"buttonBlock";
static const NSString *KEY_HitTestEdgeInsets = @"hitTestEdgeInsets";
@implementation UIButton (LXExpandBtn)
//扩大点击区域
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if(UIEdgeInsetsEqualToEdgeInsets(self.hitTestEdgeInsets, UIEdgeInsetsZero) || !self.enabled || self.hidden)
{
return [super pointInside:point withEvent:event];
}
CGRect relativeFrame = self.bounds;
CGRect hitFrame = UIEdgeInsetsInsetRect(relativeFrame, self.hitTestEdgeInsets);
return CGRectContainsPoint(hitFrame, point);
}
+(UIButton *)LXButtonWithTitle:(NSString *)title titleFont:(UIFont *)titleLabelFont Image:(UIImage *)image backgroundImage:(UIImage *)backgroundImage backgroundColor:(UIColor *)backgroundColor titleColor:(UIColor *)titleLabelColor frame:(CGRect)frame
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
[button setBackgroundImage:backgroundImage forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
[button setTitleColor:titleLabelColor forState:UIControlStateNormal];
button.backgroundColor = backgroundColor;
button.frame = frame;
button.titleLabel.font = titleLabelFont;
return button;
}
+(UIButton *)LXButtonNoFrameWithTitle:(NSString *)title titleFont:(UIFont *)titleLabelFont Image:(UIImage *)image backgroundImage:(UIImage *)backgroundImage backgroundColor:(UIColor *)backgroundColor titleColor:(UIColor *)titleLabelColor
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
[button setBackgroundImage:backgroundImage forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
[button setTitleColor:titleLabelColor forState:UIControlStateNormal];
button.backgroundColor = backgroundColor;
button.titleLabel.font = titleLabelFont;
return button;
}
//添加点击事件-
-(void)addClickBlock:(ButtonBlock)block
{
self.block = block;
[self addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
}
-(void)buttonAction:(UIButton *)button
{
self.block(button);
}
- (void)layoutButtonWithEdgeInsetsStyle:(LXButtonEdgeInsetsStyle)style
imageTitleSpace:(CGFloat)space
{
// self.backgroundColor = [UIColor cyanColor];
/**
* 前置知识点:titleEdgeInsets是title相对于其上下左右的inset,跟tableView的contentInset是类似的,
* 如果只有title,那它上下左右都是相对于button的,image也是一样;
* 如果同时有image和label,那这时候image的上左下是相对于button,右边是相对于label的;title的上右下是相对于button,左边是相对于image的。
*/
// 1. 得到imageView和titleLabel的宽、高
CGFloat imageWith = self.imageView.frame.size.width;
CGFloat imageHeight = self.imageView.frame.size.height;
CGFloat labelWidth = 0.0;
CGFloat labelHeight = 0.0;
if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
// 由于iOS8中titleLabel的size为0,用下面的这种设置
labelWidth = self.titleLabel.intrinsicContentSize.width;
labelHeight = self.titleLabel.intrinsicContentSize.height;
} else {
labelWidth = self.titleLabel.frame.size.width;
labelHeight = self.titleLabel.frame.size.height;
}
// 2. 声明全局的imageEdgeInsets和labelEdgeInsets
UIEdgeInsets imageEdgeInsets = UIEdgeInsetsZero;
UIEdgeInsets labelEdgeInsets = UIEdgeInsetsZero;
// 3. 根据style和space得到imageEdgeInsets和labelEdgeInsets的值
switch (style) {
case LXButtonEdgeInsetsStyleTop:
{
imageEdgeInsets = UIEdgeInsetsMake(-labelHeight-space/2.0, 0, 0, -labelWidth);
labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith, -imageHeight-space/2.0, 0);
}
break;
case LXButtonEdgeInsetsStyleLeft:
{
imageEdgeInsets = UIEdgeInsetsMake(0, -space/2.0, 0, space/2.0);
labelEdgeInsets = UIEdgeInsetsMake(0, space/2.0, 0, -space/2.0);
}
break;
case LXButtonEdgeInsetsStyleBottom:
{
imageEdgeInsets = UIEdgeInsetsMake(0, 0, -labelHeight-space/2.0, -labelWidth);
labelEdgeInsets = UIEdgeInsetsMake(-imageHeight-space/2.0, -imageWith, 0, 0);
}
break;
case LXButtonEdgeInsetsStyleRight:
{
imageEdgeInsets = UIEdgeInsetsMake(0, labelWidth+space/2.0, 0, -labelWidth-space/2.0);
labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith-space/2.0, 0, imageWith+space/2.0);
}
break;
default:
break;
}
// 4. 赋值
self.titleEdgeInsets = labelEdgeInsets;
self.imageEdgeInsets = imageEdgeInsets;
}
#pragma mark--- getter setter--
//分类中不能直接使用setter和getter、需要使用运行时
- (void)setHitTestEdgeInsets:(UIEdgeInsets)hitTestEdgeInsets
{
NSValue *value = [NSValue value:&hitTestEdgeInsets withObjCType:@encode(UIEdgeInsets)];
objc_setAssociatedObject(self, &KEY_HitTestEdgeInsets, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIEdgeInsets)hitTestEdgeInsets
{
NSValue *value = objc_getAssociatedObject(self, &KEY_HitTestEdgeInsets);
if(value)
{
UIEdgeInsets edgeInsets;
[value getValue:&edgeInsets];
return edgeInsets;
}
else
{
return UIEdgeInsetsZero;
}
}
-(void)setButtonId:(NSString *)buttonId{
objc_setAssociatedObject(self, &KEY_ButtonId, buttonId, OBJC_ASSOCIATION_RETAIN);
}
-(NSString *)buttonId{
return objc_getAssociatedObject(self, &KEY_ButtonId);
}
-(void)setBlock:(ButtonBlock)block{
objc_setAssociatedObject(self, &KEY_ButtonBlock, block, OBJC_ASSOCIATION_RETAIN);
}
-(ButtonBlock)block{
return objc_getAssociatedObject(self, &KEY_ButtonBlock);
}
@end

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//扩大点击区域
UIButton *button2 =[UIButton LXButtonWithTitle:@"button2" titleFont:Font(15) Image:nil backgroundImage:nil backgroundColor:[UIColor whiteColor] titleColor:[UIColor blackColor] frame:CGRectMake(0, 0, 200, 200)];
[button2 setTitleColor:[UIColor purpleColor] forState:UIControlStateHighlighted];
[button2 setTitle:@"button2点到了" forState:UIControlStateHighlighted];
button2.layer.borderColor =[UIColor redColor].CGColor;
button2.layer.borderWidth = 5;
button2.center = CGPointMake(125, 125);
button2.hitTestEdgeInsets =UIEdgeInsetsMake(-50, -50, -50, -50);
[view addSubview:button2];
[button2 addClickBlock:^(UIButton *button) {
NSLog(@"点击了button2");
}];
//布局方式
[self.topBtn layoutButtonWithEdgeInsetsStyle:LXButtonEdgeInsetsStyleTop imageTitleSpace:10];

demo 地址:UIButton扩展