Slightly more complex animations through UIView Animations

Member
Posts: 27
Joined: 2012.05
Post: #1
Hello,

While the [UIView animateWithDuration: delay: option: animations^{} completion^{}] is a great way for doing simple animations such as moving views in the same direction, or transforming the scale and rotation one way, however for more complex situations such as scaling up and scaling down in the midst of the same animation block is really difficult. The compiler does not interpret it as 2 separate animations and does the first one super quick and then goes on to the other one with respect to the duration defined in the method.

What I am trying to do, is to create a label view out of thin air in the middle of the screen and move it upwards towards the top of the screen margin and then fade out. So I am first changing alpha of the view from 0 to .8 and moving the view 75 pixels up. Then in the completion block am moving it another 75 pixels up but changing the alpha from .8 to 0. both have 0 delays. But the labelview stops for one fraction of a second, before moving onto the completion block.

Both have linear curves.

Does anyone have a good way to indent these kind of animations so that several actions can be done in a sequential form. Such as zooming and zooming out while moving in one direction, an earthquakey wiggle, becoming visible and then becoming invisible while continuing moving?

Any info/insights would help.

Thanks,
AvidGamer101
Quote this message in a reply
⌘-R in Chief
Posts: 1,260
Joined: 2002.05
Post: #2
Quick things:
a) The compiler is not involved in running your code at all.
b) Code always helps

When you say the first one happens "super quick" and because of something I think you said in the last thread, it makes me think you have some misconception of how the animation works in general. When setting animatable properties inside of the animations block, they don't happen synchronously to each other. That entire block is executed within a microsecond and the animation happens asynchronously. So if you're doing…

animations:^{ a.frame = x; a.frame = y; }

…that's not two animations that are going to run back to back. What you did was tell A that it should animate its frame from its current value to x. Then you immediately told it to instead animate to y, not x. You've reset the target value of the animation from x to y. Then when the animation actually begins (after the entire block executes) it's simply going to animate from the current value to y.

To chain animations you could use the completion block, wrapping another call to animateWithDuration:… or you could make the calls to animateWithDuration: at the same time, but make the second animation have a delay exactly equal to the duration of the first etc.
Quote this message in a reply
Member
Posts: 27
Joined: 2012.05
Post: #3
Thanks a ton Seth!

I did some more research and decided basically animate the labels using a NSTimer.

This allows for more freedom and flexibility, and I just stop the timer once the animation is completed.
Quote this message in a reply
⌘-R in Chief
Posts: 1,260
Joined: 2002.05
Post: #4
Hmm, for what you described I don't see how it's a better solution for you. Having timers around inherently means dealing with everything yourself including the memory management, while leveraging Core Animation will yield better performance and—more often than not—less code.
Quote this message in a reply
Moderator
Posts: 384
Joined: 2002.08
Post: #5
I would recommend avoiding the NSTimer, and instead using
animateWithDuration:animations:completion:

Check the "finished" boolean that is passed to the completion block to determine if it's time to fire the next animation after the first one completes. It will be set to YES when the first animation is complete.

KB Productions, Car Care for iPhone/iPod Touch
@karlbecker_com
All too often, art is simply the loss of practicality.
Quote this message in a reply
Member
Posts: 27
Joined: 2012.05
Post: #6
I tried using the animateWithDuration method, however the problem I faced was because of nested animations.

For example, I wanted a UILabel to move from one edge of the screen to the other, and while it was doing so, scale up till it reached the middle of the screen and start scaling down while it is moving towards the other edge.

This was proving to be overly difficult. So i just shifted to using NSTimers. You can do it using perform selector afterdelay, or just using a NSDelay. But it is working with the timers. I agree with you guys though, that this is not the best way to perform OS animations.

Cheers,
avidgamer101
Quote this message in a reply
⌘-R in Chief
Posts: 1,260
Joined: 2002.05
Post: #7
Well, a simple way:

Code:
[UIView animateWithDuration:1.0
        delay: 0.0
        options:0
        animations:^{
            view.frame = right;
            
            [UIView animateWithDuration:0.5
                 delay:0.0
                 options: UIViewAnimationOptionOverrideInheritedDuration |
                          UIViewAnimationOptionAutoreverse
                 animations:^{
                     view.layer.transform = CATransform3DMakeScale(2.0, 2.0, 1);
                 }
                 completion:^(BOOL finished){
                     view.layer.transform = CATransform3DMakeScale(1.0, 1.0, 1);
                 }];

        }
        completion:nil];
Quote this message in a reply
Moderator
Posts: 384
Joined: 2002.08
Post: #8
Seth, I have noticed that I need to check the "finished" boolean to really make sure that block gets called properly. Though I swear I did not need to always do that check.

Do you know if something changed in a version of iOS that requires checking the finished variable? I see you're not checking it, and I just wanted to confirm that this code would truly work as intended (meaning the completion: block would not run until the animations: block has finished all the way).

KB Productions, Car Care for iPhone/iPod Touch
@karlbecker_com
All too often, art is simply the loss of practicality.
Quote this message in a reply
⌘-R in Chief
Posts: 1,260
Joined: 2002.05
Post: #9
I'm not the one to ask about changes between OS versions. I don't do any iOS programming. Smile

In this case, if the animation is cancelled you probably don't want it hanging around at 2x scale, and always want it to be reset. It seems like there'd be no universal rule that you should only ever act on finished being true. It depends on the circumstances.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Sequential Animations avidgamer101 5 3,912 Jan 20, 2013 03:02 PM
Last Post: Mathemanic
  How do I apply a perspective transform to a UIView and add to cocos2d sefiroths 0 3,412 Sep 24, 2012 05:45 AM
Last Post: sefiroths
  How to get a UIView color of a perticular pixel(x,y)? ravi124 1 5,093 Mar 24, 2009 08:51 PM
Last Post: Holmes