views:

625

answers:

3

Hi,

I have a simple animation which simply modify the position of a button:


[UIView beginAnimation:nil context:nil];
[UIView setAnimationsDuration:3.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
mybutton.frame = CGREctMake(20, 233, 280, 46);
[UIView commitAnimations];

I want to perform some other animations when this one is finish, how to do that?

+1  A: 

Use the +[UIVIew setAnimationDelegate:] and +[UIView setAnimationDidStopSelector:] methods to configure your class to receive a message when the animation ends.

Ben Gottlieb
+1  A: 

You could look at setAnimationBeginsFromCurrentState:. All the animations are run in their own threads, so [UIView commitAnimations] is a nonblocking call. So, if you begin another animation immediately after committing the first one, after appropriately setting whether or not it begins from the current state, I think you'll get the behavior you want. To wit:

[UIView beginAnimation:nil context:nil];
// set up the first animation
[UIView commitAnimations];

[UIView beginAnimation:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:NO];
// set up the second animation
[UIView commitAnimations];

Alternately, you could provide a callback by doing something like

[UIView beginAnimation:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)
// set up the first animation
[UIView commitAnimations];

//...

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    // set up the second animation here
}
Seth Pellegrino
+1  A: 

a code segment for getting start.. setup initial (the first) animation:

- (void) aniPath:(AnimationPath *) path
{   
    [UIView beginAnimations:path->aniname context:path];
    [UIView setAnimationDuration:path->interval];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(aniDone:finished:context:)];

    // your initial animation

    [UIView commitAnimations];
}

chains to another animation when the first is done:

- (void) aniDone:(NSString *) aniname finished:(BOOL) finished context:(void *) context
{
    AnimationPath *path = (AnimationPath *) context;
    if ([aniname isEqualToString:path->aniname]) {
        [UIView beginAnimations:path->aniname context:context];
        [UIView setAnimationDuration:path->interval];
        [UIView setAnimationDelegate:self];
        [UIView setAnimationDidStopSelector:@selector(aniDone:finished:context:)];

        // more animations, even recursively 

        [UIView commitAnimations];          
    }
}
ohho
What is `AnimationPath`, and why are you using the `->` operator on it? If AnimationPath is an Objective-C class, you should definitely not be using `->`. You should never access an ivar from outside the class itself unless you have a really good reason to. You should create accessor methods, or use Obj-C properties, and use those to access `aniname` and `interval`.
Nick Forge
AnimationPath is my own struct to coordinate the animation path. You may safely ignore it or replace with your own data structure.
ohho