Вопрос

I have a UIPanGestureRecognizer attached to a view in my iOS app. I copied the code from the Touches sample app for the pan handler. When the gesture starts, my code:

  • Records the original anchor point and center.
  • Changes the anchor point and center to be around the user's fingers, like so:

    CGPoint locationInView = [gestureRecognizer locationInView:target];
    CGPoint locationInSuperview = [gestureRecognizer locationInView:target.superview];
    target.layer.anchorPoint = CGPointMake(
        locationInView.x / target.bounds.size.width,
        locationInView.y / target.bounds.size.height
    );
    target.center = locationInSuperview;
    

As the gesture progresses, the pan handler continuously changes the center to track the finger movement. So far so good.

When the user lets go, I want the view to animate back to its original starting point. The code that does that looks like this:

[UIView animateWithDuration:2 delay:0 options:UIViewAnimationCurveEaseOut animations:^{
    target.center            = originalCenter;
    target.layer.anchorPoint = originalAnchorPoint;
}];

And that does animate the view back to its original starting point. However, before the animation starts, the view jumps to a different spot in the UI. IOW, let go, it jumps, then it animates back to where it belongs.

I thought perhaps I needed to set the anchor point and center outside the animation, perhaps setting the center to the location in the super view, like when the gesture begins, but that seems to make no difference.

What am I missing here? How can I prevent the jump when the user lets go?

Это было полезно?

Решение

I suspect two issues without trying out what you are doing:

Changing the anchor point changes a view's/layer's position. In order to change an anchor point without modification of the position, you can use some helper like this one:

-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
    CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x, view.bounds.size.height * anchorPoint.y);
    CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x, view.bounds.size.height * view.layer.anchorPoint.y);

    newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
    oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);

    CGPoint position = view.layer.position;

    position.x -= oldPoint.x;
    position.x += newPoint.x;

    position.y -= oldPoint.y;
    position.y += newPoint.y;

    view.layer.position = position;
    view.layer.anchorPoint = anchorPoint;
}

(I'm using that myself in my projects. Found here: Changing my CALayer's anchorPoint moves the view)

Your animation sets the anchor point back to its original value. You should use the helper above to reset the anchor point. This ensures that the view won't move when changing the anchor. You'll have to do this outside of the animation. Afterwards, use an animation block to change the view's center and animate it to where you want it to be.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top