Pan gesture translation being reset between should-begin and handler (with state began) on iOS7
Asked Answered
T

2

18

I have a pan gesture recognizer to drag a panel up, down, left, or right. When the direction of the pan is not possible I don't allow the recognizer to begin so that the touches can go to other UI elements within the panel.

However, on iOS7 the translation sometimes gets reset between gestureRecognizerShouldBegin: and my gesture handler handlePan:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer*)panGR
{
    CGPoint trans = [panGR translationInView:self.view];
    NSLog(@"should begin trans: (%.2f, %.2f)", trans.x, trans.y);
    ...

This logs: should begin trans: (18.00, 0.00)

- (void)handlePan:(UIPanGestureRecognizer*)panGR
{
    CGPoint trans = [panGR translationInView:self.view];

    switch(panGR.state)
    {
        case UIGestureRecognizerStateBegan:
            NSLog(@"handlePan began trans: (%.2f, %.2f)", trans.x, trans.y);
            ...

This logs: handlePan began trans: (0.00, 0.00)

Which means the shared code to determine the direction of the pan (right, in this case) works in gestureRecognizerShouldBegin: and allows the gesture to begin, but then can't be determined in handlePan: when the state is UIGestureRecognizerStateBegan.

Is this a bug in iOS7 or has the behaviour deliberately changed to accommodate new gesture types? Also, can anyone suggest a good way to work around this issue?

Taurine answered 22/9, 2013 at 17:25 Comment(0)
A
1

The UIPanGestureRecognizer is always setting the translation to (0,0) after reaching the UIGestureRecognizerStateBegan state - since even the slightest translation is recognized it's designed to work as a trigger only (if you set up large threshold for beginning the recognition like (50,50) you will obviously get a "lag" in UI behavior - as a workaround I would suggest to store the value of the translation and then use a UIView animation to pan the object more smoothly). You should use the UIGestureRecognizerStateChanged for updating the translation, and UIGestureRecognizerStateRecognized for setting the end point of the pan.

Attitude answered 22/7, 2014 at 11:58 Comment(2)
I think you misunderstood the question. This translation reset happens between gestureRecognizerShouldBegin and the handler with state UIGestureRecognizerStateBegan. I think it's a bug in iOS7Taurine
what I had in mind by writing "after reaching the UIGestureRecognizerStateBegan" is that this resetting happens before the handler is called, isn't it? I understand the problem and ran some code to reproduce it - I agree with you that this behavior is very confusing and in some cases may cause trouble, e.g. in a situation when your implementation of gestureRecognizerShouldBegin returns YES only when relatively large (i.e. distances that can be seen on screen, like your (18.00, 0.00)) transition occurs. Which I understood is the case?Attitude
M
-1

You can determine the direction in handlePan: by checking if the horizontal translation is higher or lower than 0. But at the end of handlePan: you do need to reset the CGPoint of the translation as the new reference for the next translation.

- (void)handlePan:(UIPanGestureRecognizer*)panGR
{
    CGPoint translation = [gr translationInView:self.view];
    if (translation.x > 0) {
        //Direction: Right
    } else if (translation.x < 0) {
        //Direction: Left
    }


    [gr setTranslation:CGPointZero
                inView:self.view];
}
Marlin answered 28/5, 2014 at 20:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.