【问题标题】:UIControlEventTouchDragExit triggers when 100 pixels away from UIButtonUIControlEventTouchDragExit 在距离 UIButton 100 像素时触发
【发布时间】:2012-12-29 16:37:10
【问题描述】:

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

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

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

【问题讨论】:

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


    【解决方案1】:

    覆盖 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];
    }
    

    【讨论】:

    • 所以在这个例子中,它会从默认的 100px 减少到 25px?
    【解决方案2】:

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

    1. 注册的动作会被调用两次:
      • 第一次是手指离开控件25像素的时候,这个是overwritten方法中设置的。
      • 当手指离开控件大约 70 像素时调用第二次,这是 UIControl 的默认行为。
    2. 第二个问题是从event参数中检索到的位置是(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 像素的边界扩展来处理,您当然可以根据需要将此值设置为其他值。

    【讨论】:

    • 我根据这个答案写了一篇文章。是中文写的,可以找到here
    • hey feihu 能否请您将您的代码转换为当前的 swift 版本。这将更有帮助。提前致谢
    【解决方案3】:

    根据我读到的here

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

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

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

    【讨论】:

    • 我已经看过那个帖子了。你在这里回复的一半已经在我的问题中了。我正在尝试确定这些相关方法是什么,等等。
    • 对不起,我读错了你的问题。你的意思是你想要一个方法列表?
    • 这会有所帮助,但我可以自己做一些研究,这只是对开始自定义此行为所需的确切操作的总体概述——这是我第一次'曾经需要覆盖 Apple 的任何行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多