I'm trying to have an auto reversing animation, and am getting the above error on the "completion:^(BOOL)finished{" line.
[UIView animateWithDuration:0.5
delay:0
options:UIViewAnimationOptionAutoreverse
animations:^{
[[[self dieButtons] objectAtIndex:i] setTransform:CGAffineTransformMakeTranslation(0, 200)];
}
completion:^(BOOL)finished{
}];
Note I first attempted this with the following code but the button jumped to the new location at the end of the animation.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationRepeatAutoreverses:YES];
[button setTransform:CGAffineTransformMakeTranslation(0, 200)];
[UIView commitAnimations];
finished is the name of the BOOL parameter, and Objective-C blocks have C-style function signatures, so it has to be in the parentheses.
The block's signature is supposed to look like this:
^(BOOL finished) {
}
Related
I want a transition within my app that is like the mystery revolving wall from old scooby doo cartoons. I want the screen to revolve when switching views. Anyone point me in the right direction for the possibility of accomplishing this?
Or this, which uses far less ink:
UIView *bookCaseView; // this is the container... the haunted wall
UIView *booksView; // just an ordinary set of books, right?
UIView *spookyBackside; // ruh-roh, raggy!
[UIView transitionWithView:containerView
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
[booksView removeFromSuperview];
[bookCaseView addSubview:spookyBackside]; }
completion:NULL];
I think this is what you are looking for:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
//optional if you want to do something after the animation
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(myAnimationDidFinish:finished:context:)];
//
[view2 setFrame:CGRectMake(0, 0, view2.frame.size.width, view2.frame.size.height)];
[view1 addSubview:view2];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:view1 cache:YES];
[UIView commitAnimations];
And to flip back:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
//optional if you want to do something after the animation
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(myOtherAnimationDidFinish:finished:context:)];
//
[view2 removeFromSuperview];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:view1 cache:YES];
[UIView commitAnimations];
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 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.
I'm using some pretty standard code to flip 2 UIImageViews that are inside a small view.
(I'm amazed it worked!)
But what if I had THREE UIImageViews inside a small view... and wanted to flip between all 3?
I thought I could just cut/paste 2 copies of my code... but I guess not.
When I try to flip 1>2.. and then 2>3... it just flips once... going directly from 1>3.
What happened to 2????
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:myView cache:YES];
[image1 removeFromSuperview];
[myView addSubview:image2];
[UIView commitAnimations];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:myView cache:YES];
[image2 removeFromSuperview];
[myView addSubview:image3];
[UIView commitAnimations];
The animations are not chained together like this. Basically, they are doing both animations at the same time. What you want is to create a new method for the second flip that will be called after the first one is done:
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)contextn {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:myView cache:YES];
[image2 removeFromSuperview];
[myView addSubview:image3];
[UIView commitAnimations];
}
Then in your existing method, put this line:
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
like so:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:myView cache:YES];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
[image1 removeFromSuperview];
[myView addSubview:image2];
[UIView commitAnimations];
For more info, check the apple docs
You could set a 0.5 second delay on the start of the second animation.
Also, you may want to check out keyframe animations to do more advanced stuff like this.
Jill,
In your second code block, do the following.
[UIView beginAnimations:nil context:NULL];
// This will cause your second animation block to wait 0.5 second, which will be
// enough time for the second one to kick in and do it's thing.
[UIView setAnimationDelay:0.5];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:myView cache:YES];
[image2 removeFromSuperview];
[myView addSubview:image3];
[UIView commitAnimations];
I'm trying to do a multistage animation, so that a UIImageView (1) fades in, (2) moves, (3) slide off the screen.
Only stage 1 seems to work. What am I doing wrong? Here's the code:
// FIRST PART - FADE IN
-(void)firstAnim
{
// 'sprite' is a UIImageView
[sprite setAlpha:0.1f];
[UIView beginAnimations:#"anim1" context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.25];
[UIView setAnimationDidStopSelector:#selector(secondAnim)];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[sprite setAlpha:1.0f];
[UIView commitAnimations];
}
// SECOND PART - MOVE
-(void)secondAnim
{
[UIView beginAnimations:#"anim2" context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDidStopSelector:#selector(thirdAnim)];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
sprite.frame = CGRectMake(170, 184, 20, 20);
[UIView commitAnimations];
}
// THIRD PART - SLIDE OFF SCREEN
-(void)thirdAnim
{
[UIView beginAnimations:#"anim3" context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
sprite.frame = CGRectMake(170, 420, 20, 20);
[UIView commitAnimations];
}
You need to add a call to set yourself as the animation delegate:
[UIView setAnimationDelegate:self];
It would be a good idea to unset yourself as the delegate (set to nil) in the last animation block.
The complete solution to your question is:
1) set the animation delegate
2) use the correct selector and method signature
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:.5];
[UIView setAnimationDelegate:self]; //set delegate!
[UIView setAnimationDidStopSelector:
#selector(secondAnim:finished:context:)];
-(void)secondAnim:(NSString *)animationID
finished:(NSNumber *)finished
context:(void *)context {
//animation #2
}