I am using core animation to flash intermediate scores (using UILabel) in a game on iPhone. I need it to repeat for certain count for a particular hit.
The score needs to be flashed for a particular count and then disappear.
So it should go from alpha 0.0 -> 1.0 -> 0.0
Below is the code with which I am trying to achieve this.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatCount:repeatCount];
[UIView setAnimationRepeatAutoreverses:YES];
playerScore.alpha = 1.0f;
[UIView commitAnimations];
The problem is that after the animation is over, the alpha returns back to 1.0
Any suggestions?
I would use the more powerful animateWithDuration:delay:options:animations:completion: method on UIView. See View programming guide or UIView class reference
More specifically it could look like that: the method takes two blocks: one for the animation itself and one block which is execute once the animation is done. It maybe look a bit strange at first sight, but that is just the block syntax.
[UIView animateWithDuration:1.0 delay:0.f options:(UIViewAnimationOptionAutoreverse| UIViewAnimationOptionRepeat)
animations:^{
playerScore.alpha=1.f;
} completion:^(BOOL finished){
playerScore.alpha=0.f;
}];
This solution is for iOS version 4 or higher. If you want to target versions before that, you have to use a delegate callback. Set the selector to be executed when the animation is done like this:
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(flashingDidStop:finished:context:)];
//with the callback method
- (void)flashingDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
//code to execute in your case
playerScore.alpha = 0.f;
}
If you need this to work in iOS < 4.0 try this:
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
playerScore.alpha = 0.0f;
}
...
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatCount:repeatCount];
[UIView setAnimationRepeatAutoreverses:YES];
playerScore.alpha = 1.0f;
[UIView commitAnimations];
Related
I used some animations in my application.Its working fine.But while calling another animation previous animation comes old position.How to resolve these kind of problems.
Here my code:
CGRect frame = self.PickerView.frame;
frame.origin.x=0;
frame.origin.y=730;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
self.PickerView.frame=frame;
[UIView commitAnimations];
I have this code so it changes location once but then stays there when you still touch
- (IBAction)fade {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[button setAlpha: 0];
[UIView commitAnimations];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[button setAlpha: 1];
[UIView commitAnimations];
button.center = CGPointMake(152 + 16,326 + 16);
button.center = CGPointMake(200 + (kPlatformWidth/2),300 + (kPlatformHeight/2));
}
How to make it go to a random location from here?
You should not use beginAnimations:context:
To quote the docs:
Use of this method is discouraged in iOS 4.0 and later. You should use
the block-based animation methods to specify your animations instead.
You should use the new methods of the form animateWithDuration:animations:
As for how to make the button move to a random location, use arc4random_uniform to calculate new x and y positions and use those values as the destination of your view's center.
I am using the following code to make text in a label blink :
- (void)blinkAnimation:(NSString *)animationID finished:(BOOL)finished target:(UILabel *) target {
NSString *selectedSpeed = [[NSUserDefaults standardUserDefaults] stringForKey:#"EffectSpeed"];
float speedFloat = (0.50 - [selectedSpeed floatValue]);
[UIView beginAnimations:animationID context:(__bridge void *)(target)];
[UIView setAnimationDuration:speedFloat];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(blinkAnimation:finished:target:)];
if([target alpha] == 1.0f)
[target setAlpha:0.0f];
else
[target setAlpha:1.0f];
[UIView commitAnimations];
}
and I am using the following code to make the animation Stop :
- (void) stopAnimation{
[self.gameStatus.layer removeAllAnimations];
}
Although the animation works fine, I cannot stop it.
Could you please help!
Thanks in advance....
The problem is that your animationDidStopSelector is being called when you manually stop your animation, but that method is just starting another animation. So you're stopping it ok, but you're immediately firing off another animation.
Personally, I'd suggest getting rid of the animationDidStopSelector and use the autoreverse and repeat features of the animation:
[UIView beginAnimations:animationID context:nil];
[UIView setAnimationDuration:speedFloat];
[UIView setAnimationDelegate:self];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationRepeatCount:CGFLOAT_MAX];
[target setAlpha:0.0f];
[UIView commitAnimations];
That should fix it, but as holex said, you should use block animation. I quote from the documentation: "Use of this method [beginAnimations] is discouraged in iOS 4.0 and later. You should use the block-based animation methods to specify your animations instead."
So, the equivalent block animation would be:
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
animations:^{
self.gameStatus.alpha = 0.0;
}
completion:nil];
Whichever technique you use, your removeAllAnimations will now work as expected.
As an aside, when you stop animations, it will set alpha immediately to zero. It might be more graceful to stop the repeating animation and then animate the alpha from the current value to your desired final value. To do that, you'll want to grab the current opacity from the presentation layer and then animate alpha from that to whatever you want it to stop at (in my example 1.0, but you could use 0.0, too):
CALayer *layer = self.gameStatus.layer.presentationLayer;
CGFloat currentOpacity = layer.opacity;
[self.gameStatus.layer removeAllAnimations];
self.gameStatus.alpha = currentOpacity;
[UIView animateWithDuration:0.25
animations:^{
self.gameStatus.alpha = 1.0;
}];
How does one remove the acceleration and deceleration animation that UIView Animations do?
If you don't understand what I mean, when an animation starts up it accelerates and then when it get to the end, it decelerated. I want the animation to be a constant speed.
Here is an example of what my code looks like (I MUST use the old animation ways).
-(void)animate:(NSString*)animationID finished:(BOOL)finished context:(void*)context {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDidStopSelector:#selector(animateStop:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:3];
Motion.center = (*PathPoints)[Location];
[UIView commitAnimations];
}
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
I've got 2 methods in my class and in each I've got an animation. My question is, can I store these animations in one array or something and refer to them by beginAnimation:name? If yes, how can I do this?
thanks for help
-(void)hideMenu{
[UIView beginAnimations:#"HIDE_MENU" context:nil];
[UIView setAnimationDuration:0.38];
[UIView setAnimationDelay:0.12];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationBeginsFromCurrentState:YES];
self.frame = CGRectMake(0, -1 * self.frame.size.height, self.frame.size.width, self.frame.size.height);
[UIView commitAnimations];
}
-(void)showMenu{
[UIView beginAnimations:#"SHOW_MENU" context:nil];
[UIView setAnimationDuration:0.38];
[UIView setAnimationDelay:0.12];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationBeginsFromCurrentState:YES];
self.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
[UIView commitAnimations];
}
-(void)handleShowMenu:(NSNotification*)note{
[self showMenu];
}
-(void)handleHideMenu:(NSNotification*)note{
[self hideMenu];
}
You can't store UIView animations as they are not objects. Even with blocks animation api introduced in 4.0, animations are still just actions performed by static class methods. Closest thing you can do is store the blocks and reuse them, or just do what you are doing and keep compatibility with iOS versions older than 4.0.
If you really want to store your animations as objects, you should skip UIView animation and go a bit lower to Core Animation.