Ios UIControlEventTouchDragExit在距UIButton 100像素时触发

Ios UIControlEventTouchDragExit在距UIButton 100像素时触发,ios,objective-c,cocoa-touch,drag-and-drop,uitouch,Ios,Objective C,Cocoa Touch,Drag And Drop,Uitouch,目前,UIControlEventTouchDragExit仅在我从按钮拖动100像素时触发。我想定制这种行为,并将其范围扩大到25像素左右,但我对编程比较陌生,从未需要重写/定制这样的内置方法 我在这里的一些其他帖子中读到,我需要对UIButton(或者甚至可能是UIControl?)进行子类化,并覆盖-(BOOL)开始使用touch:(UITouch*)touch with event:(UIEvent*)event和相关方法,但我真的不知道从哪里开始这样做 有谁能给我一些建议,告诉我如何才

目前,
UIControlEventTouchDragExit
仅在我从按钮拖动100像素时触发。我想定制这种行为,并将其范围扩大到25像素左右,但我对编程比较陌生,从未需要重写/定制这样的内置方法

我在这里的一些其他帖子中读到,我需要对
UIButton
(或者甚至可能是
UIControl
?)进行子类化,并覆盖
-(BOOL)开始使用touch:(UITouch*)touch with event:(UIEvent*)event
和相关方法,但我真的不知道从哪里开始这样做

有谁能给我一些建议,告诉我如何才能做到这一点?非常感谢^_^

根据我读到的

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

  • -(BOOL)开始触摸:(UITouch*)触摸事件:(UIEvent*)事件
  • -(BOOL)继续跟踪触摸:(UITouch*)触摸事件:(UIEvent*)事件

以及其他相关方法

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

我发现公认的答案有两个问题

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

    注册操作: 处理事件:
    现在,所有六个事件都可以使用
    25
    pixel的边界扩展来处理,当然,您可以根据需要将此值设置为其他值

    我已经看过那篇帖子了。。你回答的一半已经在我的问题中了。我试图确定那些相关的方法是什么,等等。对不起,我把你的问题看错了。你的意思是你想要一个方法列表吗?那会很有帮助,但我可以自己做一些研究,这更多的是关于我需要做些什么来开始定制这个行为的概述-这是我第一次需要覆盖苹果的任何行为。所以在这个例子中,它将减少到25px,从默认的100像素下降到100像素?我已经根据这个答案写了一篇文章。它是用中文写的,可以找到。嘿,飞虎,你能把你的代码转换成当前的swift版本吗。那会更有帮助。提前谢谢
        // 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
            }
        }    
    }