UIControlEventTouchDragExit在距离UIButton 100像素时触发

时间:2013-01-15 14:41:53

标签: ios objective-c cocoa-touch drag-and-drop uitouch

目前,UIControlEventTouchDragExit仅在我拖离按钮100像素时触发。我想自定义此行为并将该范围调整到大约25像素,但我对编程相对较新,并且从不需要覆盖/自定义这样的内置方法。

我在其他一些帖子中读过,我需要继承UIButton(或者甚至是UIControl?),并覆盖-(BOOL) beginTrackingWithTouch: (UITouch *) touch withEvent: (UIEvent *) event及相关方法,但我不知道从哪里开始这样做。

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

3 个答案:

答案 0 :(得分: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];
}

答案 1 :(得分:7)

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

  1. 注册的操作将被调用两次:
    • 第一次是手指离开控件25个像素,这是在覆盖方法中设置的。
    • 当手指离开控件大约70个像素时,第二次调用,这是UIControl的默认行为。
  2. 第二个问题是从event参数检索的位置是(0, 0),它未正确初始化。
  3. 我找到了另一种基于这个答案实现此目的的方法,基本思想是在回调中处理事件而不是覆盖该方法。有两个步骤:

    注册操作:

        // 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像素的边界扩展来处理所有六个事件,您当然可以根据需要将此值设置为其他值。

答案 2 :(得分:1)

根据我的阅读here

Apple使用100像素来解释使用手指的不准确性。您可以使用以下方法覆盖这些方法:

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

和其他方法相关的方法。 Apple Documentation