I'm running an animation after a button touch. If the user touches the button before the current animation finishes I want the new animation to wait until the current animation finishes. How can I do so?
Nest it with the completion variation of UIView's animateWithDuration wrapper like so:
[UIView animateWithDuration:1.00 animations:^{
//animate first!
}
completion:^(BOOL finished) {
[UIView animateWithDuration:1.00 animations:^{
//animate the second time.
}];
}];
Or just set a single animation to continue from it's current state with this:
[UIView animateWithDuration:1.00
delay:0.00
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
//animate
}
completion:^(BOOL finished){
}];
I always chain my animation with this:
[self performSelector:#selector(animationDone) withObject:nil afterDelay:1.0];
Related
I new to IOS programming.
I want to toggle button border color automatically at start of apps to get user attention,
I have tried the below code, but only the final color is selected.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelay:0.0];
[UIView setAnimationDuration:3.0];
button.layer.borderWidth=2.5f;
button.layer.borderColor=[[UIColor blueColor]CGColor];
[UIView setAnimationDelay:3.0];
button.layer.borderColor=[[UIColor clearColor]CGColor];
[UIView setAnimationDelay:6.0];
button.layer.borderColor=[[UIColor redColor]CGColor];
[UIView commitAnimations];
}
What you're doing is an invalid way to chain animations. As a result, only the last changes are applied. Additionally, you should be using block based animations, which Apple has recommended since iOS 4. Should be something like this:
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderWidth=2.5f;
button.layer.borderColor=[[UIColor blueColor]CGColor];
} completion:^(BOOL finished) {
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderColor=[[UIColor clearColor]CGColor];
} completion:^(BOOL finished) {
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderColor=[[UIColor redColor]CGColor];
}];
}];
}];
This answer is the same as 0x7fffffff's answer, except it uses block variables so it looks a little cleaner and hopefully makes more sense:
void (^animateToRed)(BOOL finished) = ^(BOOL finished) {
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderColor=[[UIColor redColor]CGColor];
} completion: nil];
}
void (^animateToClear)(BOOL finished) = ^(BOOL finished) {
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderColor=[[UIColor clearColor]CGColor];
} completion:animateToRed];
}
[UIView animateWithDuration:3.0 animations:^{
button.layer.borderWidth=2.5f;
button.layer.borderColor=[[UIColor blueColor]CGColor];
} completion:animateToClear];
UIView's animateWithDuration:animations:completion: method is the best way to animate changes over time.
It takes 3 arguments.
A duration as a CGFloat, which is a measure of the length of the animation in seconds.
An animation block, which tells what animations to perform.
A completion block, which allows you to execute code after the animation is complete.
This code snippet creates two completion blocks.
The animateToRed completion block handles the animating of the border to red. It's completion block is nil, at this point, we're done animating.
The animateToClear completion block handles the animating of the border to clear. It's completion block is the animateToRed which we just defined.
Finally, we call animateWithDuration, animating the border to blue, and passing the animateToClear block for the completion (which in turn calls the animateToRed block).
For an animation this simple and with no repeated animations, it may seem like slightly overkill to do it this way (though it is slightly more readable). However, with a more complicated series of animations, especially if there's any repetitiveness, creating block variables like this to use and pass quickly becomes quite helpful.
I want an animated UIView that will move like this lever on this image. seesaw but i have no great knowledge on animations in xcode. I can only do sliding like this
[UIView animateWithDuration:1.0 delay:2.0 options:(UIViewAnimationCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction)
animations:^
{
[UIView setAnimationDelegate:self];
self.bug.center = CGPointMake(75, 200);
}
completion:^(BOOL finished)
{
NSLog(#"Move to left done");
}
];
Is there a way that i can use manipulate this code and animate it like a seesaw?
I am trying to animate one of my image form bottom to Top of my screen , for that i am implementing an animation that the current width and height of image will become half during the transition stage and will take its original size once animation completes.
The issue is once the 1st animation is done it hold's for a while and then starts another animation , i want a smooth animation .
Here is the code :
[UIView animateWithDuration:1.0
delay:0.5
options:UIViewAnimationOptionTransitionCurlUp
animations:^{
[_myImageView setFrame:CGRectMake(20.0, 220.0, currentframe.size.width/2, currentframe.size.height/2)];
} completion:^(BOOL finished)
{
if (finished)
{
[UIView animateWithDuration:1.0
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
[_myImageView setFrame:CGRectMake(20.0, 20.0, currentframe.size.width, currentframe.size.height)];
} completion:^(BOOL finished) {
if (finished) {
NSLog(#"2 nd log ");
}
}];
NSLog(#"animation fisnished !!");
}
}];
What should be done ?
try this:
[UIView animateWithDuration:1.0
delay:0
options:UIViewAnimationOptionCurveLinear// use CurveLinear option
animations:^{
} completion:^(BOOL finished) {
}];
At least I would dream of this Animation Flow:
FadeIn to 50% with alpha:0.5 for 2 seconds
Then fadeIn to 100% with alpha:1 for 2 seconds
Then fade out to 0% with alpha:0 for 4 seconds
After the visible animation ends, the text for the label shall be changed and then the fade routine should start again as shown above.
I feel that this code here does not allow the step by step fade animation and the code commences too early without waiting to finish the Fade out section.
//A FOR Loop sets text for the _label then the Animation routine should start:
- (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];
}
];
}
// Somehow the code shall wait here for ending the visible (!!) animation in the UI
// to set a new text for _label with the FOR Loop
The whole issue took me some days to figure out so far. But I am stuck here with the problem to pause the code for a while as it does not automatically wait for the visual finishing of the animation which makes it difficult for me to go on.
I'm sure that is what you are really looking for; but it meets your description:
- (IBAction)startFade:(id)sender {
[_label setAlpha:0.f];
[UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveLinear animations:^{
[_label setAlpha:0.5f];
} completion:^(BOOL finished) {
NSLog(#"1st step is done.");
[UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveLinear animations:^{
[_label setAlpha:1.f];
} completion:^(BOOL finished) {
NSLog(#"2nd step is done.");
[UIView animateWithDuration:4.f delay:0.f options:UIViewAnimationOptionCurveLinear animations:^{
[_label setAlpha:0.f];
} completion:^(BOOL finished) {
NSLog(#"3rd step is done, text will be changed.");
// let me change the text
[_label setText:[[NSDate date] description]];
// let me start the animation over, welcome to my infinite loop.
[self startFade:nil];
}];
}];
}];
}
I am using the following to make a UIImageView slide a little bit forward, and then slide back farther for a parallax scrolling effect.
Code:
[UIView animateWithDuration:0.2f animations:^{
spendrBckGrnd.frame = CGRectMake(spendrBckGrnd.frame.origin.x + 20, 0, spendrBckGrnd.frame.size.width, spendrBckGrnd.frame.size.height);
}];
[UIView animateWithDuration:0.4f animations:^{
spendrBckGrnd.frame = CGRectMake(spendrBckGrnd.frame.origin.x - 80, 0, spendrBckGrnd.frame.size.width, spendrBckGrnd.frame.size.height);
}];
I am wondering how I might go about applying some easing into the animation, right now if just abruptly slides back and forth quickly. I would like to ease into and out of the sliding animations.
You need to do the second animation block after the first one completes.
[UIView animateWithDuration:0.2f animations:^{
spendrBckGrnd.frame = CGRectMake(spendrBckGrnd.frame.origin.x + 20, 0, spendrBckGrnd.frame.size.width, spendrBckGrnd.frame.size.height);
} completion:^{
[UIView animateWithDuration:0.2f animations:^(BOOL finished){
spendrBckGrnd.frame = CGRectMake(spendrBckGrnd.frame.origin.x - 80, 0, spendrBckGrnd.frame.size.width, spendrBckGrnd.frame.size.height);
}];
}];
This will do the trick:
[UIView animateWithDuration:0.2f delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^(void){
//do your animations
} completion:^(BOOL finished){
}];
Check out this tutorial on UIView animation
http://mobile.tutsplus.com/tutorials/iphone/ios-sdk_uiview-animations/
UIView has a method
// [UIView animateWithDuration:(NSTimeInterval) delay:(NSTimeInterval) options:(UIViewAnimationOptions)animations:^(void)animations completion:^(BOOL finished)completion];
typedef enum {
UIViewAnimationCurveEaseInOut, // slow at beginning and end
UIViewAnimationCurveEaseIn, // slow at beginning
UIViewAnimationCurveEaseOut, // slow at end
UIViewAnimationCurveLinear
}
[UIView animateWithDuration:0.6f
delay:0.1f
options:UIViewAnimationCurveEaseInOut
animations:^{
[starView setCenter:CGPointMake(0, 0)];
[starView setAlpha:0.0f];
}
completion:^(BOOL finished){
[starView removeFromSuperview];
points++;
}
];
Also check out this control on github that creates a parallax effect using a custom container view, much like the top view of Path's timeline.
https://github.com/modocache/MDCParallaxView