0

I have a 2-d button array in my main view and want to be able to move them by dragging inside this view. The buttons are pretty narrow, around 23x23 pixels. I have added targets for control events touchDragExit and touchDragOutside but they were fired many pixels after I moved my finger outside the button. Hence I subclassed UIButton and overrode continueTrackingWithTouch with some code I found in SO. Notice I don't call the superclass implementation.

-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
    CGFloat boundsExtension = 5.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)
        {
            [self sendActionsForControlEvents:UIControlEventTouchDragExit];
        }
        else
        {
            [self sendActionsForControlEvents:UIControlEventTouchDragOutside];
        }
    }
    return self.tracking;
}

Both events are fired correctly but my UIControlEventTouchDragOutside action receives wrong touch info when its action is called. Here is the first part of my implementation:

-(void) dragOutside:(UIButton *) sender withEvents:(UIEvent *) event
{
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint relativeLocToInitialCell = [touch locationInView:sender];

    NSLog(@"Translation %f %f NumTouch %d",relativeLocToInitialCell.x, relativeLocToInitialCell.y, [[event allTouches] count]);
    ...   
}

[[event allTouches] count] still returns 0 until I move my finger much away from the button. Then of course relativeLocToInitialCell fields x and y are both 0, which are the values I use for later computations. Any idea what might be the problem?

EDIT: A deleted answer suggested using UIPanGestureRecognizer instead of touchdrag events, but I couldn't use it because it was firing too rapidly before handling one event I got another one.

4

1 回答 1

3

我最终不得不处理UIControlEventTouchDragInside事件。虽然这看起来是一种解决方法,但考虑这些触摸拖动事件的基本原理使其成为一个合理的解决方案。所有拖动事件均来自touchesBegan, touchesMoved and touchesEnded. Apple 在UIControlEventTouchDragOutside发送之前添加了一些阈值,但直到该阈值UIControlEventTouchDragInside事件肯定被发送。

我的解决方案是删除被覆盖的continueTrackingWithTouch方法并继续其默认实现。然后我处理了内部和外部事件,并将我的初始化代码从退出事件移动到内部事件,并在内部事件中添加了控制语句。抽象代码如下所示:

-(void) dragInside:(UIButton *) sender withEvents:(UIEvent *) event
{
    if(stillInsideOriginalControl) return;

    UITouch *touch = [[event allTouches] anyObject];
    CGPoint relativeLocToInitialCell = [touch locationInView:sender];

    [self processTouch];
}

-(void) dragOutside:(UIButton *) sender withEvents:(UIEvent *) event
{
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint relativeLocToInitialCell = [touch locationInView:sender];

    [self processTouch];
}
于 2013-05-04T19:45:13.727 回答