UIControlEventTouchDragExit在距离UIButton 100像素的位置触发。

7
目前,只有当我将按钮拖动100像素时,UIControlEventTouchDragExit才会触发。我想自定义此行为,并将该范围缩小到大约25像素,但我相对较新于编程,并且从未需要覆盖/自定义此类内置方法。
我在这里的其他帖子中阅读到,我需要子类化UIButton(或甚至UIControl?),并覆盖 - (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event 和相关方法,但我真的不知道从哪里开始。
是否有人可以友善地提供一些建议,告诉我如何实现这一点?非常感谢! ^_^
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];
}

那么在这个例子中,它将会从默认的100像素减少到25像素? - Luke

7
我发现被接受的答案有两个问题。
  1. 注册的操作会被调用两次:
    • 第一次是当手指离开控件25像素时,这是在重写的方法中设置的。
    • 第二次是当手指离开控件约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 像素来处理,当然你也可以根据需要将此值设置为其他值。

我基于这个答案写了一篇文章。它是用中文写的,可以在这里找到(http://feihu.me/blog/2015/trigger-condition-of-events-for-uibutton/)。 - feihu
嗨,飞狐,你能否把你的代码转换成当前的 Swift 版本?那将会更有帮助。先谢谢了。 - veeresh kumbar

1

根据我在这里阅读到的内容

苹果公司为了解决使用手指不准确的问题,将100个像素用于校准。您可以使用以下方法覆盖默认设置:

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

还有其他相关方法,请参考苹果文档


2
我已经看过那篇帖子了。你在这里回答的一半内容已经在我的问题中了。我正在尝试确定那些相关的方法是什么等等。 - Luke
1
抱歉,我误读了您的问题。您是指您需要方法列表吗? - Nate Lee
1
那会很有帮助,但我也可以自己进行一些研究,更多的是关于我需要做什么来开始定制这种行为的概述 - 这是我第一次需要覆盖任何苹果行为。 - Luke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接