7

目前,UIControlEventTouchDragExit只有当我将按钮拖出 100 像素时才会触发。我想自定义此行为并将该范围设置为 25 像素左右,但我对编程比较陌生,从来不需要覆盖/自定义这样的内置方法。

我在这里阅读了其他一些帖子,我需要子类化UIButton(或者甚至UIControl?),并覆盖-(BOOL) beginTrackingWithTouch: (UITouch *) touch withEvent: (UIEvent *) event和相关方法,但我真的不知道从哪里开始这样做。

任何人都可以就我如何实现这一目标提供一些建议吗?非常感激!^_^

4

3 回答 3

11

覆盖 continueTrackingWithTouch:withEvent: 像这样在默认装订线内发送 DragExit/DragOutside 事件:

- (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];
}
于 2013-01-18T13:33:17.490 回答
7

我发现接受的答案有两个问题。

  1. 注册的动作会被调用两次:
    • 第一次是手指离开控件25像素的时候,这个是overwritten方法中设置的。
    • 第二次在手指离开控件大约 70 像素时调用,这是 UIControl 的默认行为。
  2. 第二个问题是从event参数 is检索到的位置(0, 0),它没有正确初始化。

我根据这个答案找到了另一种实现此目的的方法,基本思想是在回调中处理事件而不是覆盖该方法。有两个步骤:

注册动作:

    // to get the touch up event
    [btn addTarget:self action:@selector(btnTouchUp:withEvent:) forControlEvents:UIControlEventTouchUpInside];
    [btn addTarget:self action:@selector(btnTouchUp:withEvent:) forControlEvents:UIControlEventTouchUpOutside];
    // to get the drag event
    [btn addTarget:self action:@selector(btnDragged:withEvent:) forControlEvents:UIControlEventTouchDragInside];
    [btn addTarget:self action:@selector(btnDragged:withEvent:) forControlEvents:UIControlEventTouchDragOutside];

处理事件:

- (void)btnTouchUp:(UIButton *)sender withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGFloat boundsExtension = 25.0f;
    CGRect outerBounds = CGRectInset(sender.bounds, -1 * boundsExtension, -1 * boundsExtension);
    BOOL touchOutside = !CGRectContainsPoint(outerBounds, [touch locationInView:sender]);
    if (touchOutside) {
        // UIControlEventTouchUpOutside
    } else {
        // UIControlEventTouchUpInside
    }
}

- (void)btnDragged:(UIButton *)sender withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGFloat boundsExtension = 25.0f;
    CGRect outerBounds = CGRectInset(sender.bounds, -1 * boundsExtension, -1 * boundsExtension);
    BOOL touchOutside = !CGRectContainsPoint(outerBounds, [touch locationInView:sender]);
    if (touchOutside) {
        BOOL previewTouchInside = CGRectContainsPoint(outerBounds, [touch previousLocationInView:sender]);
        if (previewTouchInside) {
            // UIControlEventTouchDragExit
        } else {
            // UIControlEventTouchDragOutside
        }
    } else {
        BOOL previewTouchOutside = !CGRectContainsPoint(outerBounds, [touch previousLocationInView:sender]);
        if (previewTouchOutside) {
            // UIControlEventTouchDragEnter
        } else {
            // UIControlEventTouchDragInside
        }
    }    
}

现在所有六个事件都可以通过像素的边界扩展来处理25,当然您可以根据需要将此值设置为其他值。

于 2015-05-19T08:17:44.900 回答
1

根据我在这里读到的

Apple 将 100 像素用于说明使用手指的不准确性。您可以使用以下方法覆盖这些方法:

  • -(BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
  • -(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event

和其他方法相关的方法。苹果文档

于 2013-01-15T21:03:02.350 回答