iOS translation and scale animation
Asked Answered
D

4

22

I'm working on UIButton animation where:

The UIButton is set in the bottom center of the screen and scaled to a small size

_menuBtn.transform = CGAffineTransformMakeScale(0.1f, 0.1f);

When the app starts it should be moving to the bottom left side of the screen as it scales or grow to its original size.

- (void)viewDidLoad
{
    [super viewDidLoad];

    _menuBtn.frame = CGRectMake(160, 513, 30, 30); 
    _menuBtn.superview.frame = CGRectMake(160, 513, 30, 30);

    _menuBtn.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
    NSLog(@"_menuBtn: %@ ; _menuBtn.superview: %@", _menuBtn, _menuBtn.superview);
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:5];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
    CGAffineTransform scaleTrans  = CGAffineTransformMakeScale(1.0f, 1.0f);
    CGAffineTransform lefttorightTrans  = CGAffineTransformMakeTranslation(-200.0f,0.0f);
    _menuBtn.transform = CGAffineTransformConcat(scaleTrans, lefttorightTrans);
    [UIView commitAnimations];

}

problem

When the animation starts the button starts moving from the bottom right side of the screen and not in the bottom center where it is and should be. Any help ?

Log Result

NSLog(@"%@", _myBtn);

2013-08-14 09:22:38.913 GJCoolNavi[339:c07] <UIButton: 0x813ea30; frame = (0 0; 0 0); opaque = NO; autoresize = TM+BM; layer = <CALayer: 0x813eaf0>>

thats before doing the animation...and the result after the animation is:

2013-08-14 09:30:25.719 GJCoolNavi[612:c07] <UIButton: 0x71206d0; frame = (160 294; 0 0); opaque = NO; autoresize = TM+BM; animations = { transform=<CABasicAnimation: 0x7536a80>; position=<CABasicAnimation: 0x7537dd0>; }; layer = <CALayer: 0x7120790>>
Durfee answered 13/8, 2013 at 10:15 Comment(2)
my first thought might be irrelevant for the topic, but why haven't you used block-based animation as the Apple recommends on iOS4 or above?Ara
First thing I thought too. It's in my answer, apparently it still doesn't work. Still trying to work out what is happening and why.Godolphin
G
28

Why don't you do this...

_menuBtn.transform = CGAffineTransformMakeScale(0.1, 0.1);

[UIView animateWithDuration:5.0
options:UIViewAnimationOptionCurveEaseOut
animations:^(){
    _menuBtn.transform = CGAffineTransformMakeScale(1.0, 1.0);
    _menuBtn.center = self.view.center;
}
completion:nil];

I'd avoid moving stuff using a transform. Change the frame instead.

EDIT

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    // for convenience I'm pulling these values out in to variables.
    float buttonWidth = _menuBtn.frame.size.width;
    float buttonHeight = _menuBtn.frame.size.height;
    float viewWidth = self.view.frame.size.width;
    float viewHeight = self.view.frame.size.height;

    // set the button frame to be the bottom center
    // note you shouldn't have to do this as Interface Builder should already place it there.
    // place the button in the horizontal center and 20 points from the bottom of the view.
    _menuBtn.frame = CGRectMake((viewWidth - buttonWidth) * 0.5, viewHeight - buttonHeight - 20, buttonWidth, buttonHeight);

    // scale the button down before the animation...
    _menuBtn.transform = CGAffineTransformMakeScale(0.1, 0.1);

    // now animate the view...
    [UIView animateWithDuration:5.0
                          delay:0.0
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
                         _menuBtn.transform = CGAffineTransformIdentity;
                         _menuBtn.frame = CGRectMake(viewWidth - buttonWidth - 20, viewHeight - buttonHeight - 20, buttonWidth, buttonHeight);
                     }
                     completion:nil];
}

Try this and let me know what happens.

Godolphin answered 13/8, 2013 at 10:28 Comment(24)
I've tried the code but what it does is it starts from the top left of the screen towards the bottom center of the screen. what my code suppose to do is that it should move from the bottom center towards the bottom left of the screen.Durfee
i created the button in the storyboard. and placed it in the bottom center of the screenDurfee
Nothing, if you use them properly. But it gets confusing (case in point) especially when you ask the button where it is. Actually... please print the frame of the button before the animation.Godolphin
i didn't get you..what do you mean by printing the frame of the button ?sorry i'm new to this stuff.Durfee
it results to null: '2013-08-13 18:42:31.797 GJCoolNavi[11313:c07] (null)'Durfee
OK, try NSLog(@"%@", _myBtn); "null" is not helpful. And pleaee put it in the question. Doing this in comments is hard to read.Godolphin
It is as I thought. You are getting confused by using transforms. The frame of the button is (0,0,0,0). When you do ... _menuBtn.transform = CGAffineTransformMakeScale(0.1, 0.1); you are removing any translation you have applied to the button and so it is moving to its frame which is top left. If you stop using transforms to move stuff around the screen then you get rid of this confusion and you wouldn't have this problem.Godolphin
Please can you post every place where you change the transform of the button.Godolphin
What is menuBtn.superview? Is the button in a separate view or is the button just in the main view?Godolphin
the button just in the main viewDurfee
You shouldn't be setting the frame of the main view. Remove the line menuBtn.spuerView.frame = ...Godolphin
removing the menuBtn.superview.frame .. still has no effects..and still the animatino is not starting at the bottom centerDurfee
i've tried your code and what it does is just it moves upward from the bottom center.Durfee
OK, changed again. Just realised that you're doing this in view did load and should really be in viewDidAppear.Godolphin
tried the code and yes it starts from the center but it moves toward the right side, which is ok....but, wheres the scale animation ?Durfee
OK, that's coming next... OK, I added the scale in now.Godolphin
it just scale to its original size in the bottom center..its not moving... it may be cause by CGAffineTransformIdentityDurfee
Have you kept in the stuff to change the frame? You still need to change the frame. And no, it isn't because of the identity transform.Godolphin
i tried CGAffineTransformIdentity after setting the button's frame and it resulted to a button moving with a curve path from the bottom right side to the bottom center while it scales up to its original sizeDurfee
OK, I give up now. I've taken the code above and copied it into a project and it works perfectly. This code works, the button starts in the bottom center and is tiny. It then animates over 5 seconds and moves to the bottom right and grows until it is full size.Godolphin
did you use storyboard in making the button ?or just created it in the code ?Durfee
I used storyboard. Are you using Auto Layout in the storyboard? If you are then this would cause an issue with the animation and you need to turn Auto Layout off (in the properties pane).Godolphin
and that's it..it's due to using auto layout...thank you so much for the help FogmeisterDurfee
We got there in the end :) No worries. Rule 4 of using AutoLayout. You can't update frames directly.Godolphin
B
7

This has solved a similar problem.

Apply a (UIButton).imageView Animation.

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
CGAffineTransform scaleTrans  = CGAffineTransformMakeScale(1.0f, 1.0f);
CGAffineTransform lefttorightTrans  = CGAffineTransformMakeTranslation(-200.0f,0.0f);
_menuBtn.imageView.transform = CGAffineTransformConcat(scaleTrans, lefttorightTrans);
[UIView commitAnimations];
Bleeding answered 19/3, 2014 at 2:19 Comment(1)
THANK YOU!!! This is the only solution which worked for me, and it working FLAWLESSLY!!!Brandiebrandise
M
2

This phenomenon indicates that your button's original frame is wrong, probably because of its auto-resizing. Try setting its frame to the bottom center before you start the animation.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    _menuBtn.superview.frame = CGRectMake(0, 513, 320, 30); // This is a quick and dirty solution to make sure your button's superview is in the right place. You probably don't want to do this and are more likely to review your view hierarchy.
    _menuBtn.frame = CGRectMake(145, 0, 30, 30); // Set the frame to the bottom center, please ensure that _menuBtn's transform hasn't been changed before this step
    _menuBtn.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:5];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
    CGAffineTransform scaleTrans  = CGAffineTransformMakeScale(1.0f, 1.0f);
    CGAffineTransform lefttorightTrans  = CGAffineTransformMakeTranslation(-200.0f,0.0f);
    _menuBtn.transform = CGAffineTransformConcat(scaleTrans, lefttorightTrans);
    [UIView commitAnimations];
}
Monetta answered 14/8, 2013 at 3:25 Comment(11)
i follow what you've suggested, by setting its frame to the bottom center..but still when applying CGAffineTransformMakeTranslation the button still start animating from the bottom right side and not from the bottom center...Durfee
The reason I could think of may be that your button's superview is also at the wrong position. Please check your button and its superview's frames before animation block. You can print the log just below the _menuBtn.transform = CGAffineTransformMakeScale(0.1f, 0.1f);, like: NSLog(@"_menuBtn: %@ ; _menuBtn.superview: %@", _menuBtn, _menuBtn.superview);Monetta
i've set the button's superview but still no effect..after i've set the superview, this is what logs shows: 2013-08-14 15:16:52.686 GJCoolNavi[12708:c07] _menuBtn: <UIButton: 0x80815c0; frame = (158.5 511.5; 3 3); transform = [0.1, 0, 0, 0.1, 0, 0]; opaque = NO; autoresize = TM+BM; layer = <CALayer: 0x8081680>> ; _menuBtn.superview: <UIView: 0x8084380; frame = (160 513; 30 30); autoresize = RM+BM; layer = <CALayer: 0x8084430>> i've print the log before the animation starts.Durfee
Ah, that's the problem! Your the origin of your button's superview is {160, 513} which is probably your bottom center position of your screen. But your button's origin is {158.5, 511.5}, which is a position relative to its superview, in other word, it's the bottom right of the screen. Please try this: _menuBtn.superview.frame = CGRectMake(0, 513, 320, 30); _menuBtn.frame = CGRectMake(145, 0, 30, 30); before the animation block. And I will update my answer.Monetta
using the code you've suggested the _menuBtn frame is (158.5 -6.5; 3 3) and the superview is (0 513; 320 30)..and still the button starts animating from the bottom right side.Durfee
@Fogmeister: any suggestions or libraries that can be use with animations ?Durfee
Try commenting the animation block and run your code. Is your button at the bottom center?Monetta
yes. i did use storyboard in creating and setting the button.Durfee
Try my updated answer. Place the code in -viewWillAppear: and set your superview.frame.origin.x to 0.Monetta
but the menuBtn.superView is the main view. i.e. self.view. Why does he need to change it at all?Godolphin
@Godolphin I doubt it. Because he got the log "_menuBtn.superview: <UIView: 0x8084380; frame = (160 513; 30 30); ". self.view couldn't be that frame. So I think his view hierarchy must be more complicated.Monetta
U
0

I have used your code and its moving from bottom center to to bottom left perfectly. Might be your superview isn't in proper rect. Please check.

Utu answered 14/8, 2013 at 8:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.