UIVIew animation - Scaling + Translating

35,023

Solution 1

Setting the frame does neither a scale nor a translation. You are either using the wrong terminology or you are using the wrong tool for the job. Scale and translate are both done using Core Graphics Affine transforms when you're looking to affect the UIView (as opposed to the layer which use Core Animation transforms).

To scale a view use

// 2x
[rotationView setTransform:CGAffineTransformMakeScale(2.0, 2.0)];

To translate, use

// Move origin by 100 on both axis
[rotationView setTransform:CGAffineTransformMakeTranslation(100.0, 100.0)];

To animate these, wrap them in an animation block. If you want to transform the view with both of these, then you need to concatenate them.

If you are not wanting scale and translation (transforms) at all, then what you mean is you want to change the view's bounds and position. These are changed with calls to

[view setBounds:newRect];
[view setCenter:newCenter];

Where newRect and newCenter are a CGRect and CGPoint respectively that represent the new position on the screen. Again, these need wrapped in an animation block.

Solution 2

Here is an example with block animation:

CGPoint newCenter = CGPointMake(100.0,100.0);

[UIView animateWithDuration: 1
                      delay: 0
                    options: (UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
                 animations:^{object.center = newCenter ; object.transform = CGAffineTransformScale(CGAffineTransformIdentity, 2.0, 2.0);}
                 completion:^(BOOL finished) { }
];

Solution 3

Try this solution :

  CGAffineTransform s =  CGAffineTransformMakeScale(0.5f,0.5f);
  CGAffineTransform t = CGAffineTransformMakeTranslation(100, 0);
  v2.transform = CGAffineTransformConcat(t,s); // not s,t

this operation is not commutative. The order is the opposite of the order when using convenience functions for applying one transform to another.

And you can use this operation to : for example (remove the Scale) :

    v2.transform =
    CGAffineTransformConcat(CGAffineTransformInvert(s), v2.transform);
Share:
35,023
Raj Pawan Gumdal
Author by

Raj Pawan Gumdal

Updated on March 12, 2020

Comments

  • Raj Pawan Gumdal
    Raj Pawan Gumdal about 4 years

    I have a view which I want to be scaled and translated to a new location by animating it. I tried to achieve it with the following code:

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:kDurationForFullScreenAnimation];
    [[self animatingView] setFrame:finalRect];
    [UIView commitAnimations];
    

    The effect of this code is, the view first changes its content's size to the finalRect and then translates it to the new location. i.e. The scaling part is never animated. The view is just transformed to the new size and then translated.

    This issue is already discussed in several other threads but none of them draw a conclusion. A solution does exist though, to use a timer and set the frame each time in the timer callback, but it has a performance drawback.

    What is the most appropriate solution to this problem, also, why in first case this problem occur?

    Thanks

  • Raj Pawan Gumdal
    Raj Pawan Gumdal over 13 years
    The thing is, if I do like this, the contents of view and all its sub-views assume the newRect immediately. They are not animated to the new frame. Like say you have an imageView as a subView to the animating view, the image in imageView is not scaled gradually. Rather the image is first blown up to the newRect and then the view's bounds scales + translates. Changing the center works in the animation block though, but changing the bounds doesnt as expected.
  • magnusMTB
    magnusMTB over 8 years
    Great answer. Of all my searching, this one got me exactly to what I needed to make this animation work just as I need it. I am trying to duplicate the animation as seen on Android when selecting a text field having the label shrink smaller and up and to the left. Just a scale transform shrinks the label, but down and to the right. The translation transform was also needed, but I could not find a way to get both to work. The CGAffineTransformConcat was the key. Thanks!