Fade In Fade Out Animation

Here is some code I struggle with for a while.

If you start the fade in animation, the label text fades in. If I start the fade out animation the the label text fades out.

When I start the startFade method, only fade out is shown. How can I wait for the fadeIn method to finish visually before starting the fadeOut method.

-(IBAction)startFade:(id)sender{
    [self fadeIn];
    [self fadeOut];
}

-(IBAction)fadeIn:(id)sender{
    [self fadeIn];
}

-(IBAction)fadeOut:(id)sender{
[self fadeOut];
}

-(void) fadeIn{
    [_label setAlpha:0];
    [UILabel beginAnimations:NULL context:nil];
    [UILabel setAnimationDuration:2.0];
    [_label setAlpha:1];
    [UILabel commitAnimations];
}

-(void) fadeOut{
    [UILabel beginAnimations:NULL context:nil];
    [UILabel setAnimationDuration:2.0];
    [_label setAlpha:0];
    [UILabel commitAnimations];
}

Solution 1:

When you call the fadeIn and fadeOut methods back to back like you're doing, the code is run instantaneously, so you'll only see animation from the last method called. UIView block based animation provides a completion handler, which seems to be exactly what you're looking for. So your code might looks something like this:

-(IBAction)startFade:(id)sender {

    [_label setAlpha:0.0f];        

    //fade in
    [UIView animateWithDuration:2.0f animations:^{

        [_label setAlpha:1.0f];

    } completion:^(BOOL finished) {

        //fade out
        [UIView animateWithDuration:2.0f animations:^{

            [_label setAlpha:0.0f];

        } completion:nil];

    }];
}

Swift:

@IBAction func startFade(_ sender: AnyObject) {

    label.alpha = 0.0

    // fade in
    UIView.animate(withDuration: 2.0, animations: { 
        label.alpha = 1.0
    }) { (finished) in
        // fade out
        UIView.animate(withDuration: 2.0, animations: {
            label.alpha = 0.0
        })
    }
}

Solution 2:

that does the job for you (the _label is your label);

- (IBAction)startFade:(id)sender {
    [_label setAlpha:0.f];

    [UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveEaseIn animations:^{
        [_label setAlpha:1.f];
    } completion:^(BOOL finished) {
        [UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
            [_label setAlpha:0.f];
        } completion:nil];
    }];
}

Solution 3:

Try this..

// Fade Out

 -(void)fadeOut:(UIView*)viewToDissolve withDuration:(NSTimeInterval)duration   andWait:(NSTimeInterval)wait
{
[UIView beginAnimations: @"Fade Out" context:nil];

// wait for time before begin
[UIView setAnimationDelay:wait];

// druation of animation
[UIView setAnimationDuration:duration];
viewToDissolve.alpha = 0.0;
[UIView commitAnimations];
}

// Fade In

-(void) fadeIn:(UIView*)viewToFadeIn withDuration:(NSTimeInterval)duration andWait:(NSTimeInterval)wait

{
[UIView beginAnimations: @"Fade In" context:nil];

// wait for time before begin
[UIView setAnimationDelay:wait];

    // druation of animation
[UIView setAnimationDuration:duration];
viewToFadeIn.alpha = 1;
[UIView commitAnimations];

}

// Fade in from fade out

-(void) fadeInFromFadeOut: (UIView*)viewToFadeIn withDuration:(NSTimeInterval)duration
{
    viewToFadeIn.hidden=NO;
    [self fadeOut:viewToFadeIn withDuration:1 andWait:0];
    [self fadeIn:viewToFadeIn withDuration:duration andWait:0];

}

// Button operation

-(void) buttonClicked :(id)sender
{
   NSLog(@"Button clicked");

// Each button is given a tag
int tag = ((UIButton*)sender).tag;
if (tag ==1)
{
    sprite.alpha  =1;
    [self fadeOut : sprite withDuration: 10 andWait : 1 ];
}
else if (tag ==2)
{
    sprite.alpha  =0;
    [self fadeIn : sprite withDuration: 3 andWait : 1 ];
}
else
{
    [self fadeInFromFadeOut:sprite withDuration:10];
}
}

View this link to download sample..

Refer this link.

Happy to share with you..:-)

Solution 4:

Generic answer : You can use this method to apply animation to any UIView object . First create an extension of UIView class . Create a separate swift file and write the code like this

import Foundation
import UIKit

extension UIView {

    func fadeIn() {
        //Swift 2
        UIView.animateWithDuration(1.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {
            self.alpha = 1.0
        }, completion: nil)

        //Swift 3, 4, 5
        UIView.animate(withDuration: 1.0, delay: 0.0, options: UIView.AnimationOptions.curveEaseIn, animations: {
            self.alpha = 1.0
        }, completion: nil)
    }


    func fadeOut() {
        //Swift 2
        UIView.animateWithDuration(1.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
            self.alpha = 0.0
        }, completion: nil)

        //Swift 3, 4, 5
        UIView.animate(withDuration: 1.0, delay: 0.0, options: UIView.AnimationOptions.curveEaseOut, animations: {
            self.alpha = 0.0
        }, completion: nil)
    }


}

Here self refers to any UIView you refer to . You can use buttons, labels etc to call these 2 methods .

Then in any other swift class you can call fadeIn() and fadeOut() like this :

self.yourUIObject.fadeIn()
self.yourUIObject.fadeOut()

This gives the desired effect of animation to any UIObject .

Solution 5:

you can do something like this (check possible parameters values and similar methods here : https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html

[UIView animateWithDuration:duration
                      delay:delay
                    options:option 
                 animations:^{
                     //fade in here (changing alpha of UILabel component)
                 } 
                 completion:^(BOOL finished){
                    if(finished){
                      //start a fade out here when previous animation is finished (changing alpha of UILabel component)
                 }];
}