Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIPanGestureRecognizer on a UIView behaves oddly after UIViews layer is animated

I have a series of UIViews which I animate along an arc. Each view has a UIPanGestureRecognizer on it which before any animation occurs works as expected.

However after animating the views (with the method below which animates a view's layer) the gestures do not work as expected; in fact it appears as if they work in their original screen positions.

I've tried various things including matching up the views frame and/ or bounds with that on the animated layer and even removing the existing gestures and creating and adding them again (not shown below).

If anyone knows what's going on or can get me on the road to fixing the issue it would be greatly appreciated.

EDIT: iMartin's suggestion to change

pathAnimation.removedOnCompletion = NO;

to

pathAnimation.removedOnCompletion = YES;

and

view.layer.position = ... //

have put me on the way to fixing the issue.

Original Code:

- (void)animateUIViewAlongArc:(UIView*)view clockwise:(BOOL)clockwise duration:(float)duration
{
    [UIView animateWithDuration:duration animations:^{

    CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimationanimationWithKeyPath:@"position"];
    pathAnimation.calculationMode = kCAAnimationPaced;
    pathAnimation.fillMode = kCAFillModeForwards;
    pathAnimation.removedOnCompletion = NO;
    pathAnimation.repeatCount = 1;

    CGPoint viewCenter = view.objectCenter;
    CGMutablePathRef arcPath = CGPathCreateMutable();
    CGPathMoveToPoint(arcPath, NULL, viewCenter.x, viewCenter.y);

    float angleOfRotation = self.angleIncrement;
    if (clockwise == NO)
    {
        angleOfRotation *= -1.0f;
    }

    float fullwayAngle = view.angle + angleOfRotation;
    CGPoint fullwayPoint = pointOnCircle(self.center, self.radius, fullwayAngle);

    CGPathAddRelativeArc(arcPath, NULL, self.center.x, self.center.y, self.radius, view.angle, angleOfRotation);
    pathAnimation.path = arcPath;
    CGPathRelease(arcPath);

    [view.layer addAnimation:pathAnimation forKey:@"arc"];

    view.angle = fullwayAngle;
    view.objectCenter = fullwayPoint;

    } completion:^(BOOL finished){
        if (finished)
        {
            CGRect frame = view.layer.frame;
            CGRect bounds = view.layer.bounds;

            view.frame = frame;
            view.bounds = bounds;
        }
    }];

}

like image 499
Damo Avatar asked Oct 22 '22 00:10

Damo


1 Answers

Did you check the frame of the view/layer after the animation?

I think the problem is, that what you see is not what you get. The layer itself didn't changes its position/frame, but just its presentationLayer did. Presentation layer is what you actualy see onthe screen. You could see this if you remove this line:

pathAnimation.removedOnCompletion = NO; // Delete or set to YES

Setting this to NO caused the presentation layer to be on screen at different position than your view.
What you should do, is to set final position to the layer just before adding the animation to it.

view.layer.position = finalPosition; // You should calculate this
[view.layer addAnimation:pathAnimation forKey:@"arc"];
like image 191
Tricertops Avatar answered Oct 24 '22 03:10

Tricertops