有時候我們希望讓 UIButton 的點擊範圍比視覺上還要大
此時可以對 UIButton 建立一個 Category
新增一些 method 來設定點擊範圍
實作
最理想狀況是可以分別控制上下左右的延長範圍
View source on Github
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
| @interface UIButton(EnlargeTouchArea)
@end
@implementation UIButton(EnlargeTouchArea)
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);
}
- (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
{
CGRect rect = [self enlargedRect];
if (CGRectEqualToRect(rect, self.bounds))
{
return [super hitTest:point withEvent:event];
}
return CGRectContainsPoint(rect, point) ? self : nil;
}
@end
|
原理
利用 objective-c 中的 objc_setAssociatedObject 來記錄要變大的範圍。
objc_setAssociatedObject 是 objective-c runtime library 裡面的 function。
Objective-C Runtime Reference
要使用需要import:
1
| #import <objc/runtime.h>
|
最後,最重要的是去 override - (UIView) hitTest:(CGPoint) point withEvent:(UIEvent) event
用新設定的 Rect 來當做點擊範圍。
How to use
在建立 Button 時,就可以直接設定 Button 的點擊範圍
1
2
3
4
5
6
7
8
9
10
| UIButton* enlargeButton1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[enlargeButton1 setTitle:@"Enlarge Button" forState:UIControlStateNormal];
[enlargeButton1 setFrame:CGRectMake(90, 150, 100, 50)];
[enlargeButton1 addTarget:self action:@selector(onButtonTap:) forControlEvents:UIControlEventTouchUpInside];
[enlargeButton1 sizeToFit];
[self.view addSubview:enlargeButton1];
// 增加 button 的點擊範圍
[enlargeButton1 setEnlargeEdgeWithTop:20 right:20 bottom:20
left:0];
|
小結
Category 搭配 Associative 真的是蠻好用的!
View source on Github