Autolayout violates translation rotation animation

10,334

Solution 1

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

Solution 2

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.

Solution 3

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];
}
Share:
10,334
Dima Deplov
Author by

Dima Deplov

Co-founder of pleeq.com and all related projects, including macilove.com blog with self made blog platform engine. Get in touch with me on Twitter @dimadeplov

Updated on June 25, 2022

Comments

  • Dima Deplov
    Dima Deplov almost 2 years

    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.

  • Dima Deplov
    Dima Deplov over 10 years
    I didn't open a link yet, but do you want to said, that I must "remove" constraints from my UIView, transform it and then add back constraints?
  • Max Steinmeyer
    Max Steinmeyer over 10 years
    No, I'm saying that you should not have any constraints connected to your view while its transform is not the identity transform.
  • Brian Sachetta
    Brian Sachetta about 9 years
    While this isn't the correct answer per se, it does lead to an incredibly informative post about the source of the problem. Very helpful. Thank you!
  • Max Steinmeyer
    Max Steinmeyer about 9 years
    FWIW, this is very different (and much better!) in iOS 8; in general, transforms and auto layout play well together now.