soulshined
soulshined

Reputation: 10622

Commit A Different Animation(s) While Another Animation is ending

I'm trying to create a 'wave' effect of UIView animations.

I have numerous layers to animate. I'm currently animating them with animateWithDuration:delay:options:animations:completion:

I have the views displayed in a stack so for example:

-------------------------------
|           VIEW 1            |
-------------------------------
|           VIEW 2            |
-------------------------------
|           VIEW 3            |
-------------------------------
|           VIEW 4            |
-------------------------------
|           VIEW 5            |
-------------------------------
|           VIEW 6            |
-------------------------------

This is important to know because UIView transitions are not what I'm going after.

I can easily animate them and concurrently activate the next view animation in the completion block of the previous view. So this is how it's currently set up:

[UIView animateWithDuration:0.4f animations:^{ 
    self.view1.alpha = 1.0;
} completion:^(BOOL finished) {
    [UIView animateWithDuration:0.4f animations:^{
      self.view2.alpha = 1.0;
    } completion:^(BOOL finished) {
           etc...
    }];
}];

What i would like to do, instead of concurrently activating the next view animation I would like it to activate while the previous views animation is ending. So say, the last half of time in the animation process, start the next views animation to get a wave effect. None of the UIViewAnimationOptions match my criteria, and I've also researched the developer forums for a similar goal, with no results.

What I have tried:

The workaround that I've tried is adding a delay to the next UIView animations inside the animations block as opposed to the completion block, but I feel this isn't a healthy take on the matter. Ex:

[UIView animateWithDuration:0.4f animations:^{
    //Other animations...
    self.view1.alpha = 1.0f
    [UIView animateWithDuration:0.4f delay:0.2f options:UIViewAnimationOptionAllowUserInteraction animations:^{
        self.view2.alpha = 1.0f;
    } completion:^(BOOL finished) {
         //repeat..     
    }];
}];

As you can see my work around, well, works. But as I stated above, it doesn't feel an iota of healthy. What am I missing?


EDIT

I inevitably went the route of using UIViewAnimationOptions by delaying and autoreversing the durations:

NSTimeInterval duration = 3.0;
NSTimeInterval delay = 0.5f;

[UIView animateWithDuration:duration delay:0.0f options:(UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionAllowUserInteraction) animations:^{
    self.view1.alpha = 1.0f;
} completion:^(BOOL finished) {

}];
[UIView animateWithDuration:duration delay:delay options:(UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionAllowUserInteraction) animations:^{
    self.view2.alpha = 1.0f;
} completion:^(BOOL finished) {

}];
[UIView animateWithDuration:duration delay:delay*2 options:(UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionAllowUserInteraction) animations:^{
    self.view3.alpha = 1.0f;
} completion:^(BOOL finished) {

}];
etc...

Upvotes: 1

Views: 249

Answers (1)

Eric Qian
Eric Qian

Reputation: 2256

You can use CALayer animation instead of UIView animation to achieve this. Just configure the begin time, duration and the animation on each view's layer. Here is a quick Swift example:

for (var i, v) in enumerate(views) {
    let animation = CABasicAnimation(keyPath:"opacity")
    animation.toValue = 0.0
    animation.duration = 0.4
    animation.beginTime = CACurrentMediaTime() + 0.2 * i
    v.layer.addAnimation(animation, forKey: "wave")
}

Upvotes: 1

Related Questions