Fade In Fade Out Animation - ios

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];
}

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
})
}
}

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];
}];
}

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 .

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..:-)

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)
}];
}

Based on #holex's answer, but simplified a bit (as commented):
- (IBAction)startFade:(id)sender {
[_label setAlpha:0.f];
[UIView animateWithDuration:2.f
delay:0.f
options:UIViewAnimationOptionCurveEaseIn
| UIViewAnimationOptionAutoreverse
animations:^{
[_label setAlpha:1.f];
}
completion:nil];
}

Swift 4
If you need just one pulse when clicking the button, use that:
#IBAction func didPressButton(_ sender: UIButton) {
self.someView.alpha = 0
UIView.animate(withDuration: 0.4,
delay: 0,
options: [.curveEaseInOut, .autoreverse],
animations: {
self.someView.alpha = 1
},
completion: { _ in
self.someView.alpha = 0
})
}

Swift 5 version of iPhoneDeveloper's answer:
extension UIView {
func fadeIn() {
UIView.animate(withDuration: 1.0, delay: 0.0, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.alpha = 1.0
}, completion: nil)
}
func fadeOut() {
UIView.animate(withDuration: 1.0, delay: 0.0, options: UIView.AnimationOptions.curveEaseOut, animations: {
self.alpha = 0.0
}, completion: nil)
}
}

The easiest way would be to use:
[UIView animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion]
and add the fadeOut call to the completion block. The documentation might help answer any questions you have.
If you can't use the block version for some reason, then you'll have to set a delegate ([UIView setAnimationDelegate:(id)delegate]) and a selector with ([UIView setAnimationDidStopSelector:]) that the delegate will respond to.
Again, see the documentation for more details.

My task was to make a label fade out. And then fade in with changed text. The solution was:
-(void)performAnimationOnHistoryButtonLabelUpdatingTextTo:(NSString *)text
{
[UIView animateWithDuration:0.4f animations:^{
[self.historyButtonLabel setAlpha:0.0f];
} completion:^(BOOL finished) {
self.historyButtonLabel.text = text;
[UIView animateWithDuration:0.4f animations:^{
[self.historyButtonLabel setAlpha:1.0f];
} completion:nil];
}];
}

labelAnimate = (UILabel*) [self.view viewWithTag:101];
btnTapMe = (UIButton*) [self.view viewWithTag:100];
[btnTapMe addTarget:self action:#selector(startAnimating:) forControlEvents:UIControlEventTouchUpInside];
//////////////
-(void) startAnimating:(UIButton*)button {
[labelAnimate setAlpha:0.0];
[NSTimer scheduledTimerWithTimeInterval:1.8 target:self selector:#selector(continuousEaseInOut) userInfo:button repeats:YES];
}
-(void) continuousFadeInOut {
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
[labelAnimate setAlpha:1.0];
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[labelAnimate setAlpha:0.0];
} completion:nil];
}];
}

I strongly suggest you use a generic implementation so you can reuse the code whenever you need the fade effect again.
You should create an UIView extension:
UIView+Animations.h
#import <Foundation/Foundation.h>
#interface UIView (Animations)
- (void)fadeInWithCompletion:(void (^ __nullable)(BOOL finished))completion;
- (void)fadeOutWithCompletion:(void (^ __nullable)(BOOL finished))completion;;
#end
UIView+Animations.m
#import "UIView+Animations.h"
#implementation UIView (Animations)
- (void)fadeInWithCompletion:(void (^ __nullable)(BOOL finished))completion {
[UIView animateWithDuration:2 animations:^{
[self setAlpha:1];
} completion:completion];
}
- (void)fadeOutWithCompletion:(void (^ __nullable)(BOOL finished))completion {
[UIView animateWithDuration:2 animations:^{
[self setAlpha:0];
} completion:completion];
}
#end
So, you only have to import the new file to your class or inside your Prefix.pch and use it like this:
[_label fadeOutWithCompletion:^(BOOL finished) {
[_label fadeInWithCompletion:nil];
}];
Note that you could also use nil as the completion parameter when you have nothing else to do after completion.
I also recommend you do not parameterize the duration to keep a pattern through you entire application.
This implementation can be used in the future for UIButton, UILabel, UITextField... Well, any class derived from UIView.

The fade in and fade out animations can be combined using UIView.animate(withDuration: animations:)
UIView.animate(withDuration: animationDuration, animations: {
myView.alpha = 0.75
myView.alpha = 1.0
})

Related

Create A Shadow(or blur) when user Click on UIbutton?

I have a One Uibutton in Buttom. when User click on that button a uiview animation is display like popup from buttom to up.
this is my code
-(void)viewDidLoad
{
[super viewDidLoad];
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 1000, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
}
- (IBAction)animated:(id)sender
{
if(_isAnimated)
{
[UIView animateWithDuration:0.3
delay:0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 520, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
}
completion:^(BOOL finished){
}];
_isAnimated=NO;
}
else
{
[UIView animateWithDuration:0.3
delay:0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 1000, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
}
completion:^(BOOL finished)
{
}];
_isAnimated=YES;
}
}
Uiview animation is perfectly working but when uiview appear than background view is create shadow(or blur)like uiactionsheet and after finished animation background view is clear.
i dont know how to implemented.
plz help me
i am new in ios...
You can add a UIView in background and set its backgroundcolor black and alpha 0.5 in storyboard. Then change its alpha from 0.5 to 0 with animation. You can also add an UITapGestureRecognizer to detect taps on it and dissmiss the view when user taps outside.
-(void)viewDidLoad
{
[super viewDidLoad];
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 1000, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
}
- (IBAction)animated:(id)sender
{
if(_isAnimated)
{
[UIView animateWithDuration:0.3
delay:0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 520, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
//showing background view here
self.viewBackground.alpha = 0.5;
}
completion:^(BOOL finished){
}];
_isAnimated=NO;
}
else
{
[UIView animateWithDuration:0.3
delay:0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 1000, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
//dismissing background view here
self.viewBackground.alpha = 0.0;
}
completion:^(BOOL finished)
{
}];
_isAnimated=YES;
}
}
For detecting taps outside and dismissing your view:
Create a UITapGestureRecognizer:
#interface ViewController ()
{
UITapGestureRecognizer *tapGesture;
}
Initialize it in ViewDidLoad:
-(void)viewDidLoad
{
//defining your gesture method
tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handleSingleTapGesture:)];
//adding gesture recognizer on the background view
[self.backgroundView addGestureRecognizer:tapGestureRecognizer];
}
In your Gesture Recognizer Method:
-(void)handleSingleTapGesture:(UITapGestureRecognizer *)tapGestureRecognizer
{
[UIView animateWithDuration:0.3
animations:^{
//dismissing background view here
self.viewBackground.alpha = 0.0;
}
completion:^(BOOL finished){
}];
}
Hope this helps.
add your code in viewdidload.add QuartzCore framework
#import <QuartzCore/CAAnimation.h>
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 1000, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
CABasicAnimation *animate = [CABasicAnimation animationWithKeyPath:#"shadowOpacity"];
animate.fromValue = [NSNumber numberWithFloat:1.5];
animate.toValue = [NSNumber numberWithFloat:0.5];
animate.duration = 1.0;
[self.BuyButtonPopUpView.layer addAnimation:animation forKey:#"shadowOpacity"];
self.BuyButtonPopUpView.layer.shadowOpacity = 0.0;
you can add a UIVisualEffectView first then add the popup over this view.
here is a tutorial link https://www.raywenderlich.com/84043/ios-8-visual-effects-tutorial

Dismiss a view with animation

I am popping the couponDetailsView with bounce animation. But i want to dismiss the view from left to right animation. How can i do this? Below is my source code. Any kind of help would be really helpful.
#pragma mark Bounce Animation
-(void) openContentDetailsView
{
[self.view bringSubviewToFront:self.couponDetailsView];
[UIView animateWithDuration:0.2 animations:
^(void){
self.couponDetailsView.transform = CGAffineTransformScale(CGAffineTransformIdentity,1.1f, 1.1f);
self.couponDetailsView.alpha = 0.5;
}
completion:^(BOOL finished){
[self bounceOutAnimationStoped];
}];
}
- (void)bounceOutAnimationStoped
{
[UIView animateWithDuration:0.1 animations:
^(void){
self.couponDetailsView.transform = CGAffineTransformScale(CGAffineTransformIdentity,0.9, 0.9);
self.couponDetailsView.alpha = 0.8;
}
completion:^(BOOL finished){
[self bounceInAnimationStoped];
}];
}
- (void)bounceInAnimationStoped
{
[UIView animateWithDuration:0.1 animations:
^(void){
self.couponDetailsView.transform = CGAffineTransformScale(CGAffineTransformIdentity,1, 1);
self.couponDetailsView.alpha = 1.0;
}
completion:^(BOOL finished){
[self animationStoped];
}];
}
- (void)animationStoped
{
}
- (IBAction)contentDetailsCloseButtonAction:(id)sender {
self.couponDetailsView.alpha = 0;
self.couponDetailsView.transform = CGAffineTransformScale(CGAffineTransformIdentity,0.6, 0.6);
}
Try this:
[UIView animateWithDuration:0.3f
delay:0.0f
options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
animations:^{
[testView setFrame:CGRectMake(x, y, width, height)];
} completion:^(BOOL finished) {
[testView removeFromSuperview];
}];

ios show Button with animation show one by one here i add link

I have six button on view with two pair of two grid.The problem is how to show button with animation, here I attach example url how to create this type of animation.
In this example when you click on menu button then show button in side menu view with animation
https://github.com/djardon/SideMenuFrostedAnimated
I tried this but I can't get any success.
I have two button one is btnHome and second is btnAbout:
-(void)animationStart
{
[btnHome setAlpha:0.f];
[UIView animateWithDuration:1.f delay:0.f options:UIViewAnimationOptionCurveEaseIn animations:^{
[btnHome setAlpha:0.f];
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
[btnHome setAlpha:1.f];
[self animationStart2];
} completion:nil];
}];
}
-(void)animationStart2
{
[btnAbout setAlpha:0.0f];
//fade in
[UIView animateWithDuration:2.0f animations:^{
[btnAbout setAlpha:1.0f];
} completion:^(BOOL finished) {
//fade out
[UIView animateWithDuration:2.0f animations:^{
[btnAbout setAlpha:0.0f];
} completion:nil];
}];
}
Try this.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
btnHome.alpha=0.0;
btnAbout.alpha=0.0;
}
-(void)animationStart
{
[UIView animateWithDuration:0.4f delay:0.0f options: UIViewAnimationOptionCurveEaseInOut animations:^{
btnHome.alpha=1.0;
} completion:^(BOOL finished) {
[self animationStart2];
}];
}
-(void)animationStart2
{
[UIView animateWithDuration:0.4f delay:0.0f options: UIViewAnimationOptionCurveEaseInOut animations:^{
btnAbout.alpha=1.0;
} completion:^(BOOL finished) {
}];
}
- (IBAction)btnClick:(id)sender
{
[self animationStart];
}
Here initially i am setting the buttons alpha value to 0.0f. On click of third button i am showing these two buttons.

iOS Button not clickable during animation

When I added animation to my button using a category method, then I can't click that button, seems it is disabled:
[_compassCalibrateButton pulse:1.5 continuously:YES];
_compassCalibrateButton.userInteractionEnabled=YES;
I have a UIView category contatining this :
- (void)pulse:(float)secs continuously:(BOOL)continuously {
[UIView animateWithDuration:secs/2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
// Fade out, but not completely
self.alpha = 0.3;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:secs/2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
// Fade in
self.alpha = 1.0;
}
completion:^(BOOL finished) {
if (continuously) {
[self pulse:secs continuously:continuously];
}
}];
}];
}
From the doc
During an animation, user interactions are temporarily disabled for
the views being animated. (Prior to iOS 5, user interactions are
disabled for the entire application.) If you want users to be able to
interact with the views, include the
UIViewAnimationOptionAllowUserInteraction constant in the options
parameter.
So your code should be
- (void)pulse:(float)secs continuously:(BOOL)continuously {
[UIView animateWithDuration:secs/2
delay:0.0
options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
animations:^{
// Fade out, but not completely
self.alpha = 0.3;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:secs/2
delay:0.0
options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
animations:^{
// Fade in
self.alpha = 1.0;
}
completion:^(BOOL finished) {
if (continuously) {
[self pulse:secs continuously:continuously];
}
}];
}];
}
I tested on Swift 4
UIView.animate(withDuration: 0.8, delay: 0, options: [.repeat, .autoreverse, .allowUserInteraction], animations: {
// Do Something
}, completion: nil)
Try this it will help you
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
for (UIButton *button in self.arrBtn)
{
if ([button.layer.presentationLayer hitTest:touchLocation])
{
// This button was hit whilst moving - do something with it here
[button setBackgroundColor:[UIColor cyanColor]];
NSLog(#"Button Clicked");
break;
}
}
}
Note that if you are animating a UIButton to fade out after a while, e.g.:
[UIView animateWithDuration:1.0 delay:3.0 options:|UIViewAnimationOptionAllowUserInteraction animations:^{
self->btn.alpha = 0;
} completion:nil];
It will be unresponsive from the very start, regardless your 'delay', due to the final alpha. One way around this is something like:
[UIView animateWithDuration:1.0 delay:3.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
self->btn.alpha = 0.1;
} completion:^(BOOL finished){self->btn.alpha = 0;}];

The proper way of doing chain animations

void (^first_animation)();
void (^second_animation)(BOOL finished);
// First animation
first_animation = ^()
{
g_pin_info_screen.view.alpha = 1.0;
};
// Second animation
second_animation = ^(BOOL finished)
{
g_shadow_layer.opacity = 0.0;
void (^set_opacity_to_1)();
set_opacity_to_1 = ^()
{
g_shadow_layer.opacity = 1.0;
};
[UIView animateWithDuration : 2.0
delay : 0.0
options : UIViewAnimationCurveEaseInOut
animations : set_opacity_to_1
completion : nil
];
};
// Begin the animations
{
float duration;
duration = 0.35;
[UIView animateWithDuration : duration
delay : 0.00
options : UIViewAnimationCurveEaseInOut
animations : first_animation
completion : second_animation
];
}
First animation executes as expected. But second animation completes but without any animation.
Hope somebody could comment on whether the above scheme is the proper way of doing this or not.
__block NSMutableArray* animationBlocks = [NSMutableArray new];
typedef void(^animationBlock)(BOOL);
// getNextAnimation
// removes the first block in the queue and returns it
animationBlock (^getNextAnimation)() = ^{
if ([animationBlocks count] > 0){
animationBlock block = (animationBlock)[animationBlocks objectAtIndex:0];
[animationBlocks removeObjectAtIndex:0];
return block;
} else {
return ^(BOOL finished){
animationBlocks = nil;
};
}
};
[animationBlocks addObject:^(BOOL finished){
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
//my first set of animations
} completion: getNextAnimation()];
}];
[animationBlocks addObject:^(BOOL finished){
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
//second set of animations
} completion: getNextAnimation()];
}];
[animationBlocks addObject:^(BOOL finished){
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
//third set
} completion: getNextAnimation()];
}];
[animationBlocks addObject:^(BOOL finished){
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
//last set of animations
} completion:getNextAnimation()];
}];
// execute the first block in the queue
getNextAnimation()(YES);
With the help of the third party library there is a solution that looks like as below:
First, for convenience, define a category for UIView like so:
+(RXPromise*) rx_animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations
{
RXPromise* promise = [RXPromise new];
[UIView animateWithDuration:duration animations:animations: ^(BOOL finished){
// ignore param finished here
[promise fulfillWithValue:#"finished"]; // return just a string indicating success
}];
return promise;
}
Then, define any number of asynchronous animations which execute one after the other, as follows:
[UIView rx_animateWithDuration:duration animation:^{
... //define first animation
}]
.then(^id(id result){
// ignore result, it contains the fulfill value of the promise, which is #"finished"
return [UIView rx_animateWithDuration:duration animation:^{
... // define second animation
}];
}, nil)
.then(^id(id result){
return [UIView rx_animateWithDuration:duration animation:^{
... // define third animation
}];
}, nil)
.then(^id(id result){
return [UIView rx_animateWithDuration:duration animation:^{
... // and so force
};
}, nil);
The above statement is asynchronous!
With one line additional code you can achieve cancellation:
RXPromise* rootPromise = [UIView rx_animateWithDuration:duration animation:^{
... //define first animation
}];
rootPromise.then(^id(id result){
return [UIView rx_animateWithDuration:duration animation:^{
... // define second animation
}];
}, nil)
.then(^id(id result){
return [UIView rx_animateWithDuration:duration animation:^{
... // define third animation
}];
}, nil)
...
// later, in case you need to cancel pending animations:
[rootPromise cancel];
"RXPromise" library is available on GitHub: RXPromise. It's specifically designed for these use cases, and more. Due to full disclosure: I'm the author ;)
Just check here:
https://gist.github.com/vadimsmirnovnsk/bce345ab81a1cea25a38
You can chain it in functional style:
dispatch_block_t animationsBlock = ^{
[self.view updateConstraintsIfNeeded];
[self.view layoutIfNeeded];
};
[[[[[[[[[BARAnimation construct]
initially:animationsBlock]
animationWithDuration:0.425 animationConditions:^{
[gridView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(imageView).with.offset(32.0);
}];
} animations:animationsBlock]
animationWithDuration:0.425 animationConditions:^{
[gridView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(imageView).with.offset(0.0);
}];
} animations:animationsBlock]
animationWithDuration:0.425 animationConditions:^{
[gridView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(imageView).with.offset(-32.0);
}];
} animations:animationsBlock]
animationWithDuration:0.425 animationConditions:^{
[gridView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(imageView).with.offset(0.0);
}];
} animations:animationsBlock]
animationWithDuration:0.8 animationConditions:nil animations:^{
foreView.alpha = 1.0;
}]
finally:^{
[self.didEndSubject sendNext:[RACUnit defaultUnit]];
[self.didEndSubject sendCompleted];
}]
run];
You need to chain them together by using + (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
Within the options: argument, you need to include UIViewAnimationOptionBeginFromCurrentState
Good luck!
In the completion handler of the first animation, start the second one.

Resources