4
votes

I have UIView, I want to animate it with rotation. I want to use autolayout too. I already saw a lot of stackoverflow common questions, but I didn't find any applicable solution. So, let's start with my interface and animation code; I have a UIView with image, which must be rotated. And right now I have button, that activates rotation. In the screenshot you can see red cross, this is must be the center of rotation (right now it's on the image, but I want to make center of rotation outside of the rotated UIView, I know that this could be archived with AnchorPoint).

enter image description here

This is my rotation animation code:

#define ROTATE_DURATION 3.0

- (IBAction)rotateArrow {

CGAffineTransform transform = self.hand.transform;

NSLog(@"layer possition before animation x: %f; y: %f",self.hand.layer.position.x,self.hand.layer.position.y);

[UIView animateWithDuration:ROTATE_DURATION/3 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{

        self.hand.transform = CGAffineTransformRotate(transform, 2*M_PI/3) ;
        [self.hand layoutIfNeeded];

        NSLog(@"layer possition after animation 1 x: %f; y: %f",self.hand.layer.position.x,self.hand.layer.position.y);
     }
    completion:^(BOOL finished) {
        [UIView animateWithDuration:ROTATE_DURATION/3 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{

            self.hand.transform = CGAffineTransformRotate(transform, -2*M_PI/3) ;
            [self.hand layoutIfNeeded];

            NSLog(@"layer possition after animation 2 x: %f; y: %f",self.hand.layer.position.x,self.hand.layer.position.y);
        }
    completion:^(BOOL finished) {
        [UIView animateWithDuration:ROTATE_DURATION/3 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{

            self.hand.transform = CGAffineTransformRotate(transform, 0) ;
            [self.hand layoutIfNeeded];

            NSLog(@"layer possition after animation 3 x: %f; y: %f",self.hand.layer.position.x,self.hand.layer.position.y);
        }
        completion:^(BOOL finished) {

        }];
    }];
}];



} 

So, what's the problem: When rotation is in progress UIView changes it's center and layer.position property, that's why my UIView is "jumps" when animated. If autolayout is turned off, animation is okay. I watched WWDC 2012 "Auto Layout by Example" and found that is I would use [self.hand layoutIfNeeded]; all be just fine, but it isn't at all. Animation became a little smoother, but I see this "jumps". So, here is my "output".

enter image description here

When it's animating, UIView goes to right as you can see on image, and than backs to normal position. How can I fix this "jumps"?

Here is a log:

 layer possition before animation x: 160.000000; y: 99.500000
 layer possition after animation 1 x: 197.349030; y: 114.309601
 layer possition after animation 2 x: 197.349030; y: 114.309601
 layer possition after animation 3 x: 160.000000; y: 99.500000

Thanks.

3

3 Answers

5
votes

When I layout my views, all started to work just fine. When you make a transform, it's important to remember, that autolayout always calculate your views bounds and frame, based on constraints that you set. So, in my case, I just added center vertical and horizontal align, width and height to my rotated view, so the autolayout mechanism knows when exactly my view is. And all goes just fine. Here is a good autolayout tutorial:

http://www.raywenderlich.com/50319/beginning-auto-layout-tutorial-in-ios-7-part-1

2
votes

You may be running into the general incompatibility between autolayout and transforms. Take a look there for more details, but the short story is that you probably don't want to use autolayout on the same view that is being transformed.

2
votes

The solution is:

  1. Create a container view that uses auto layout.
  2. The rotate view (that has the transform applied to it) should use auto resizing.
  3. Add the rotate view to the container view.

Create the views:

// Create container view
{
    self.mContainerView = [[UIView alloc] init];
    self.mContainerView.translatesAutoresizingMaskIntoConstraints = NO;
}

// Create view who will have the transform 
{
    self.mRotateView = [UIButton buttonWithType:UIButtonTypeCustom];
    self.mRotateView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;        
        [self.mContainerView addSubview:self.mRotateView];
}

Handle the transform:

{
    CGFloat lAngle = 180.0;    
    [UIView animateWithDuration:0.5 delay:0.0 options: UIViewAnimationOptionAllowUserInteraction |UIViewAnimationOptionCurveLinear animations:^{
            CGAffineTransform transform = CGAffineTransformMakeRotation(lAngle);
            self.mRotateView.transform = transform;
        } completion:NULL];
}