嗯,我想最好表明我的意思:
您可以清楚地看到,一旦我们触摸按钮并移出按钮,随后的移入事件会触发从远处按钮状态的变化。
虽然这种行为对于所有UIButton都很自然,但我无法谷歌解决方案来改变它。
有没有办法减少此类UIButton灵敏度的命中区域?我希望它减少,因为我觉得按钮足够大,它会提供更好的用户体验以及上/下音效。
UPD: UIButton的以下覆盖代码已在another thread中发布:
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
CGFloat boundsExtension = 25.0f;
CGRect outerBounds = CGRectInset(self.bounds, -1 * boundsExtension, -1 * boundsExtension);
BOOL touchOutside = !CGRectContainsPoint(outerBounds, [touch locationInView:self]);
if(touchOutside)
{
BOOL previousTouchInside = CGRectContainsPoint(outerBounds, [touch previousLocationInView:self]);
if(previousTouchInside)
{
NSLog(@"Sending UIControlEventTouchDragExit");
[self sendActionsForControlEvents:UIControlEventTouchDragExit];
}
else
{
NSLog(@"Sending UIControlEventTouchDragOutside");
[self sendActionsForControlEvents:UIControlEventTouchDragOutside];
}
}
return [super continueTrackingWithTouch:touch withEvent:event];
}
它改变了Drag In / Drag Out事件使用的命中区域扩展,但按钮Up / Down状态切换方式与之前完全相同。
答案 0 :(得分:2)
Swift版本:
private let _boundsExtension: CGFloat = 0 // Adjust this as needed
override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
let outerBounds: CGRect = CGRectInset(bounds, -1 * _boundsExtension, -1 * _boundsExtension)
let currentLocation: CGPoint = touch.locationInView(self)
let previousLocation: CGPoint = touch.previousLocationInView(self)
let touchOutside: Bool = !CGRectContainsPoint(outerBounds, currentLocation)
if touchOutside {
let previousTouchInside: Bool = CGRectContainsPoint(outerBounds, previousLocation)
if previousTouchInside {
sendActionsForControlEvents(.TouchDragExit)
} else {
sendActionsForControlEvents(.TouchDragOutside)
}
} else {
let previousTouchOutside: Bool = !CGRectContainsPoint(outerBounds, previousLocation)
if previousTouchOutside {
sendActionsForControlEvents(.TouchDragEnter)
} else {
sendActionsForControlEvents(.TouchDragInside)
}
}
return true
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch: UITouch = touches.first!
let outerBounds: CGRect = CGRectInset(bounds, -1 * _boundsExtension, -1 * _boundsExtension)
let currentLocation: CGPoint = touch.locationInView(self)
let touchInside: Bool = CGRectContainsPoint(outerBounds, currentLocation)
if touchInside {
return sendActionsForControlEvents(.TouchUpInside)
} else {
return sendActionsForControlEvents(.TouchUpOutside)
}
}
答案 1 :(得分:1)
我不知道你是否还有同样的问题,但我可以通过在touchesEnded:withEvent:方法中使用类似的代码来修复它。
我还改变了添加touchEnter和dragInside的方法,因为使用当前代码,那些事件仍使用相同的边界。另外我让每个案例都返回YES,这样就不会调用super(这会导致内部的触摸拖动被过早调用)。
以下是我最终得到的最终代码,有两种方法:
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
CGFloat boundsExtension = 25.0f;
CGRect outerBounds = CGRectInset(self.bounds, -1 * boundsExtension, -1 * boundsExtension);
BOOL touchOutside = !CGRectContainsPoint(outerBounds, [touch locationInView:self]);
if(touchOutside) {
BOOL previousTouchInside = CGRectContainsPoint(outerBounds, [touch previousLocationInView:self]);
if(previousTouchInside) {
[self sendActionsForControlEvents:UIControlEventTouchDragExit];
return YES;
}
else
{
[self sendActionsForControlEvents:UIControlEventTouchDragOutside];
return YES;
}
}
else {
BOOL previousTouchOutside = !CGRectContainsPoint(outerBounds, [touch previousLocationInView:self]);
if (previousTouchOutside) {
[self sendActionsForControlEvents:UIControlEventTouchDragEnter];
return YES;
}
else {
[self sendActionsForControlEvents:UIControlEventTouchDragInside];
return YES;
}
}
return [super continueTrackingWithTouch:touch withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGFloat boundsExtension = 25.0f;
CGRect outerBounds = CGRectInset(self.bounds, -1 * boundsExtension, -1 * boundsExtension);
BOOL touchInside = CGRectContainsPoint(outerBounds, [touch locationInView:self]);
if (touchInside) {
return [self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
else {
return [self sendActionsForControlEvents:UIControlEventTouchUpOutside];
}
return [super endTrackingWithTouch:touch withEvent:event];
}
注意:没有必要在最后返回方法的超级,但我把它留在那里是为了完整。