kiteloop
kiteloop

Reputation: 1107

Animated moving and rotating a UIView doesn't quite work

I want to create an animation that moves and rotates a UIView at the same time. I tried the following code:

[UIView beginAnimations:@"MoveAndRotateAnimation" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; 
[UIView setAnimationDuration:kAnimationDuration];

myView.frame = newFrame;
myView.transform = CGAffineTransformMakeRotation(0.4);

[UIView commitAnimations];

The result is, that after the animation has finished the view is drawn incorrectly (some parts are not visible anymore). If I only change the frame OR the transformation for the animation, the view draws correctly. The problem only occurs if I set both the frame and transformation.

What would be the correct way to animate moving and rotating of a view at the same time?

Upvotes: 5

Views: 6712

Answers (4)

Sabby
Sabby

Reputation: 2592

You need to do this:

#pragma mark (Woblling animation)   
    CGAffineTransform leftWobble = CGAffineTransformRotate(CGAffineTransformIdentity, RADIANS(-10.0));
    CGAffineTransform rightWobble = CGAffineTransformRotate(CGAffineTransformIdentity, RADIANS(10.0));

    self.view .transform = leftWobble;  // starting point
    [UIView beginAnimations:@"wobble" context:self.view ];
    [UIView setAnimationRepeatAutoreverses:YES]; // important
    [UIView setAnimationRepeatCount:11];
    [UIView setAnimationDuration:1.00];
    //[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(wobbleEnded:finished:context:)];//should be same as written
    self.view .transform = rightWobble; // end here & auto-reverse
    [UIView commitAnimations];

and then implement these methods. They are necessary to keep your view in the same position after rotation.

- (void) wobbleEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context 
{
    if ([finished boolValue]) {
        UIView* item = (UIView *)context;
        item.transform = CGAffineTransformIdentity;
    }
}

Use this method if you are using navigation and when you navigate from one view to another, then your view would be at the same place.else leave this method:

- (void)viewWillAppear:(BOOL)animated
{
    UIView* item = self.view;
    item.transform = CGAffineTransformIdentity;
}

I had the same problem but did some experiments and came up with this solution.

Upvotes: 0

Mike
Mike

Reputation: 8963

You can't use frame, bounds, or center if you are also animating things like rotation. You need to use CGAffineTransforms for everything and concatenate them together. Like so:

CGAffineTransform transform = CGAffineTransformMakeTranslation(100,100);
transform = CGAffineTransformRotate(transform, 0.4);

[UIView beginAnimations:@"MoveAndRotateAnimation" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; 
[UIView setAnimationDuration:kAnimationDuration];

myView.transform = transform;

[UIView commitAnimations];

Upvotes: 9

Ali
Ali

Reputation: 859

The problem is probably with your new frame size as compared to original frame size. View frame is a bit tricky when you rotate a frame: Frame is in superviews coordinate system. So, when you rotate a rectangle, the new frame will be the smallest rectangle in superview's coordinate system which contains the view. e.g. if you have a square view with frame size of (100*100) and rotate it by 45 degrees your new frame would have a size of (141*141) and if you set the frame to have a size of (100*100) you'll cut part of your view. Look at here for better understanding of how view frame works.

Upvotes: 0

sudo rm -rf
sudo rm -rf

Reputation: 29524

Try doing it this way: (Moving left and rotating, just for example)

[UIView beginAnimations:@"MoveAndRotateAnimation" context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; 
[UIView setAnimationDuration:kAnimationDuration];

CGPoint center         = CGPointMake(-200, self.view.center.y);
self.view.transform    = CGAffineTransformMakeRotation(-0.5);
self.view.center       = center;

[UIView commitAnimations];  

The center point locations would be the point you wish to make the view move, of course.

Upvotes: 4

Related Questions