I have 5 different animations that animate then disappear one after another. Is there a way to put them on an infinite loop so animation #1 begins and ends, then anim #2 begins and ends etc..? the whole process then would repeat on an infinite loop.
I have the animations in separate blocks on delays. I'm guessing that there is a better way of doing this. this is what I have at the moment:
-(void) firstAnimation {
[UIView beginAnimations:#"Fade Out Image" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDelay:40];
[UIView setAnimationRepeatCount:30];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
theImage.alpha = 1;
theImage.alpha = 0.1;
[UIView commitAnimations];
[self secondAnimation];
}
-(void) secondAnimation {
tapImage2.hidden = NO;
[UIView beginAnimations:#"Fade Out Image" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDelay:53];
[UIView setAnimationRepeatCount:29];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
theImage2.alpha = 1;
theImage2.alpha = 0.1;
[UIView commitAnimations];
[self thirdAnimation];
}
this then goes on for 5 animations. thanks for any help.
Instead of using the delay, set the animation delegate and create an animation done method. I notice you are already setting the delegate.
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context {
//Start next animation based on the animationID of the last one...
}
Related
I have an animation in my app that grows a UIImageView and then shrinks it (really two animations). Throughout the app this may happen on several different UIImageViews. I found a way to do this that worked really well, but it now doesn't seem to be compatible with Automatic Reference Counting. Here is my code:
[UIView beginAnimations:#"growImage" context:imageName];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDelegate:self];
imageName.transform = CGAffineTransformMakeScale(1.2, 1.2);
[UIView commitAnimations];
and then:
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(UIImageView *)context {
if (animationID == #"growImage") {
[UIView beginAnimations:#"shrinkImage" context:context];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDelegate:self];
context.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView commitAnimations];
}
}
This worked perfectly and I was very happy with it, until I tried converting my project to ARC. I now get the error "Implicit conversion of an Objective-C pointer to 'void *' is disallowed with ARC" on these lines in which I try to pass a UIImageView as the context for the animation:
[UIView beginAnimations:#"growImage" context:imageName];
[UIView beginAnimations:#"shrinkImage" context:context];
Does anybody know of another way that I can alert the "animationDidStop" function of which UIImageView I want it to act on that would be compliant with ARC?
Thanks so much in advance!
Any reason you are not using the much simpler block based animation?
[UIView animateWithDuration:0.5 animation:^{
imageName.transform = CGAffineTransformMakeScale(1.2, 1.2);
} completion ^(BOOL finished) {
[UIView animateWithDuration:0.5 animation:^{
imageName.transform = CGAffineTransformMakeScale(0.01, 0.01);
}];
}];
You can do as follows:
[UIView beginAnimations:#"growImage"
context:(__bridge void*)imageName];
imageName.transform = ...
[UIView commitAnimations];
I am using animation on a button click first time show a view and second ti me hide a view.
here is my code for hiding a view
-(IBAction)clickme
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDelegate:self];
[view1 setAlpha:0.0];
[UIView commitAnimations];
}
similar code is there for showing the view.
But the problem arises when user click the button many times again and again....means i am using 2 seconds for my animation but if user presses the same button in during the animation then the output result is very bad.
I don't want to disable that button during the period of animation.
Is there any other way?
You need to keep track of whether there's an animation going on, and ignore the click if it is.
Declare an instance variable BOOL animating; in your class header, and initialise it to NO in your init.
Then,
-(IBAction)clickme
{
if (animating) return;
animating = YES;
[UIView beginAnimations:nil context:self];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDelegate:self];
[view1 setAlpha:0.0];
[UIView commitAnimations];
}
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
if (context == self)
animating = NO;
}
try to use + (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState:
-(IBAction)clickme
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDelegate:self];
[view1 setAlpha:0.0];
[UIView commitAnimations];
}
this my code
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.5];
if ([sender tag] == 1) {
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:placeholder cache:YES];
}
else {
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
}
if (view1OnTop) {
[view1 removeFromSuperview];
[placeholder addSubview:view2];
}
else {
[view2 removeFromSuperview];
[placeholder addSubview:view1];
}
[UIView commitAnimations];
view1OnTop = !view1OnTop;
i want to continuously flip the view, for say some duration 1 min.
it should be continuously flipping.
how can i do it.
what i m trying to is, i want a view, which should be continuously flipping for some particular amount of time.
how can i achieve this?
regards
Apart from the flipping animation, which I presume you have working, you need to initiate a new animation when the current one is finished.
Before [UIView commitAnimations], do this:
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDone:finished:context:)];
add a function
-(void)animationDone:(NSString*)id finished:(NSNumber*)n context:(void*)context
and let that fire the next round.
edit: you do this by putting in the code to fire an animation, so the typical block from [UIView beginAnimations...] to [UIView commitAnimations]. The better solution of course is to put the animation starting code in a separate function, so the outline will look like:
...
[self startAnimationLoop];
...
-(void)startAnimationLoop
{
[UIView beginAnimtions...];
// do the animation stuff
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDone:finished:context:)];
[UIView commitAnimations];
}
-(void)animationDone:(NSString*)id finished:(NSNumber*)n context:(void*)context
{
[self startAnimationLoop];
}
to make it go back/forth, add some state variable, or create 2 sets of these functions which call eachother (startAnimationLoop1 and startAnimationLoop2, each one firing the other when done)
I have a simple animation which simply modify the position of a button:
[UIView beginAnimation:nil context:nil];
[UIView setAnimationsDuration:3.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
mybutton.frame = CGREctMake(20, 233, 280, 46);
[UIView commitAnimations];
I want to perform some other animations when this one is finish, how to do that?
You could look at setAnimationBeginsFromCurrentState:. All the animations are run in their own threads, so [UIView commitAnimations] is a nonblocking call. So, if you begin another animation immediately after committing the first one, after appropriately setting whether or not it begins from the current state, I think you'll get the behavior you want. To wit:
[UIView beginAnimation:nil context:nil];
// set up the first animation
[UIView commitAnimations];
[UIView beginAnimation:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:NO];
// set up the second animation
[UIView commitAnimations];
Alternately, you could provide a callback by doing something like
[UIView beginAnimation:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)
// set up the first animation
[UIView commitAnimations];
//...
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
// set up the second animation here
}
a code segment for getting start.. setup initial (the first) animation:
- (void) aniPath:(AnimationPath *) path
{
[UIView beginAnimations:path->aniname context:path];
[UIView setAnimationDuration:path->interval];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(aniDone:finished:context:)];
// your initial animation
[UIView commitAnimations];
}
chains to another animation when the first is done:
- (void) aniDone:(NSString *) aniname finished:(BOOL) finished context:(void *) context
{
AnimationPath *path = (AnimationPath *) context;
if ([aniname isEqualToString:path->aniname]) {
[UIView beginAnimations:path->aniname context:context];
[UIView setAnimationDuration:path->interval];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(aniDone:finished:context:)];
// more animations, even recursively
[UIView commitAnimations];
}
}
Use the +[UIVIew setAnimationDelegate:] and +[UIView setAnimationDidStopSelector:] methods to configure your class to receive a message when the animation ends.
it quite easier.
you can just
- (void)animationDidContiune:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIView *currentObj = context;
[self callTheAnimation: currentObj];
}
you can easily loop the animation.
To end it - I would create an animationDidEnded and use it instead of animationDidContiune
once you want to stop it (like simple if in animation that chooses either to contiune or end).
HF.
AND WHAT's IMPORTANT:
use this type of animating meths:
- (void)callTheAnimation:(UIView*)itemView
{
[UIView beginAnimations:#"animation" context:itemView];
.
.
.
}
they are quite flexible - you can animate whatever here due to hierarchy of the objects.
I would like to have an UIImageView that flickers. I thougt I can make it with CoreAnimation and the alpha-value. I tried this:
for (int a = 1; a <= 100; a++) {
schwarz.alpha = 0.7;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:1];
schwarz.alpha = 0,1;
[UIView commitAnimations];
}
but it doenst work. He just moves to 0.1 and not again to 0.7.
I also tried this:
schwarz.alpha = 0.7;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:1];
schwarz.alpha = 0.1;
[UIView commitAnimations];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:1];
schwarz.alpha = 1;
[UIView commitAnimations];
[UIView commitAnimations];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:1];
schwarz.alpha = 3;
[UIView commitAnimations];
// and so on...
And again It doenst work. How can I implement the flickering?
Thanks!
The problem with your code is that the [UIView commitAnimation] method doesn't block - I mean that the code implementation continues and the animation is done asynchronously.
So, actually, what is going on is that you go through all the loop iterations first and then the animation is done from 0.7 to 1.0...
Just use the setAnimationDidStopSelector without the "for" loop.
schwarz.alpha = 0.7;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:1];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
schwarz.alpha = 0.1;
[UIView commitAnimations];
The catching method might be:
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
/* Do your things here... */ }
All UIView animations added in one event loop are basically merged together. You need to use the UIView animationDidStopSelector. As an example, see the following:
-(void)tileAnimate:(NSString*)animationID finished:(BOOL)finished context:(void*)context {
int position = [animationID intValue];
NSString *next = [NSString stringWithFormat:#"%d", position+1];
if(position == boardSize) {
return;
}
[UIView beginAnimations:next context:context];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:timing];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(tileAnimate:finished:context:)];
buttons[position].transform = CGAffineTransformIdentity;
[UIView commitAnimations];
}
I use this to, one after another, animate shrinking an array of buttons back to their normal sizes.
Two more things:
First, UIViewAnimationCurveEaseIn does not work fading i think.
Second, in your original code you say:
schwarz.alpha = 0,1;
Note that there is a comma there and not a dot. Interestingly that code compiles, but it probably does not do what you intended.
Here is another take on this. I'm not using fading but I think the flickering effect is still nice.
http://github.com/st3fan/iphone-experiments/tree/master/Miscellaneous/Flicker/
Use the first code sample posted, but take out the for statement and add the lines
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationRepeatCount:(float)number];
I think -1 for the number should be repeating indefinitely, but I'm not 100% sure on that.