最近因为项目需求,需要仿照微信语音聊天界面,就研究了一下UIButton的事件响应。“按住说话”,“松开结束”,“向上移动,取消发送”这种逻辑,一看使用UIButton的响应事件做应该最简单。可是尝试过使用UIButton的响应事件UIControlEventTouchUpInside等响应事件区域的朋友可能就不会这样认为了。下面是我对UIButton响应事件区域的详细研究。
UIButton响应事件:
UIControlEventTouchUpInside
UIControlEventTouchUpOutside
UIControlEventTouchDragInside
UIControlEventTouchDragOutside
UIControlEventTouchDragEnter
UIControlEventTouchDragExit
先说结论:事件UpInside和UpOutside的切换的临界值为70;事件DragInside和DragOutside的切换的临界值为70;事件DragEnter和DragExit的切换的临界值为70。可能苹果觉得人的手指比较小,所以事件的边界值设置多出了70个像素。所以如果要想自定义这个临界值,可以参考下面的代码(主要逻辑:计算手指的位置和超出button的距离)。
贴上代码:
CGFloat const kBoundsExtension = 10.f;
// create button
UIButton *button = [UIButton new];
[self.view addSubview:button];
button.frame = CGRectMake(0, 0, 100, 40);
button.center = self.view.center;
[button setTitle:@"按钮" forState:UIControlStateNormal];
button.backgroundColor = [UIColor lightGrayColor];
// add actions
[button addTarget:self action:@selector(buttonTouchUp:withEvent:) forControlEvents:UIControlEventTouchUpInside];
[button addTarget:self action:@selector(buttonTouchUp:withEvent:) forControlEvents:UIControlEventTouchUpOutside];
[button addTarget:self action:@selector(buttonDrag:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button addTarget:self action:@selector(buttonDrag:withEvent:) forControlEvents:UIControlEventTouchDragOutside];
// upinside / upoutside
- (void)buttonTouchUp:(UIButton *)sender withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGRect outerBounds = CGRectInset(sender.bounds, -1 * kBoundsExtension, -1 * kBoundsExtension);
BOOL touchOutside = !CGRectContainsPoint(outerBounds, [touch locationInView:sender]);
if (touchOutside) {
// UIControlEventTouchUpOutside
NSLog(@"----UpOutside");
} else {
// UIControlEventTouchUpInside
NSLog(@"----UpInside");
}
}
// dragin / dragout / dragEnter / dragExit
- (void)buttonDrag:(UIButton *)sender withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGRect outerBounds = CGRectInset(sender.bounds, -1 * kBoundsExtension, -1 * kBoundsExtension);
BOOL touchOutside = !CGRectContainsPoint(outerBounds, [touch locationInView:sender]);
if (touchOutside) {
BOOL previewTouchInside = CGRectContainsPoint(outerBounds, [touch previousLocationInView:sender]);
if (previewTouchInside) {
NSLog(@"----DragExit");
// UIControlEventTouchDragExit
} else {
// UIControlEventTouchDragOutside
NSLog(@"----DragOutside");
}
} else {
BOOL previewTouchOutside = !CGRectContainsPoint(outerBounds, [touch previousLocationInView:sender]);
if (previewTouchOutside) {
// UIControlEventTouchDragEnter
NSLog(@"----DragEnter");
} else {
// UIControlEventTouchDragInside
NSLog(@"----DragInside");
}
}
}