I currently have a view animating from one part of the screen to another. I want the animation to pause whenever the "pause" button is pressed. This means the animation needs to remain right where it is (frame location) when I "pause" the animation. I've tried a few things but nothing has given me the result I want. Below is a rough version of my current code.
-(IBAction)startScroll
{
NSLog(#"Start scroll");
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:30];
//set new frame for view
[UIView commitAnimations];
}
and one method to stop the animation
-(IBAction)pauseScroll
{
NSLog(#"Pause Scroll");
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:0.1];
//Pause animation in it's current location
[UIView commitAnimations];
}
Ended up going with a timer and updating the contentOffset every few seconds. Wish there was a better way to get a view current coords even during an animation. The presentationLayer stuff did not yield successful results.
UIView animations don't quite work like that. Once you set the frame, the view instantly moves there from your app's perspective; it's just the display to the user that's animated.
You can use the "presentation layer" to figure out roughly what's being displayed on screen (it's only approximate since the compositing happens in another thread):
#import <QuartzCore/CALayer.h>
...
[fooView setFrame:fooView.layer.presentationLayer.frame]
Related
This is an absolute beginner's question (sorry), but I was wondering how to commit one animations and once it has ended to start another one. Imagine having an image moved from x=0 to x=300. Then you want to do animate the same image again, but this time from x=300 to x=330 so that it disappears from the screen.
The following code will only do the animation from x=300 to x=330 and will not commit the animation x=0 to x=300. I'm sure I don't get the concept of commitAnnimation and that this is obvious, but how would I do two animations after one another?
I know I could move the image straightaway to 330, but I don't want this as I need the first animation (x 0 - 300) to be in sync with another animation.
Here is my (wrong) code:
[UIView beginAnimations:#"shadowMove" context:nil]; // Begin animation
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[imageView setFrame:CGRectOffset([imageView frame], 300, 0)];
[UIView commitAnimations]; // End animations
// Second Animation
[UIView beginAnimations:#"shadowMoveRestAway" context:nil]; // Begin animation
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[imageView setFrame:CGRectOffset([imageView frame], 330, 0)]; // Move imageView off screen
[UIView commitAnimations]; // End animations
Use the delegate method
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
to start something else when the first animation has finished. So put what you want to do next inside the animationDidStop:finished:context method, remember that the iphone is an event driven environment so linear code like you have above will simply kick off each animation at almost the same time.
EDIT:
I forgot to add that you need to set the animation delegate as well otherwise you won't get the event when the first one stops - see below;
Here's a full version of your code with the change - I'm using the abbreviated animationDidStop delegate as that's easier to understand and fine for this example.
[UIView beginAnimations:#"shadowMove" context:nil]; // Begin animation
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(myFirstAnimationDidStop)];
[imageView setFrame:CGRectOffset([imageView frame], 300, 0)];
[UIView commitAnimations]; // End animations
Then you just need a new method like this;
-(void) myFirstAnimationDidStop {
// Second Animation
[UIView beginAnimations:#"shadowMoveRestAway" context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[imageView setFrame:CGRectOffset([imageView frame], 330, 0)];
[UIView commitAnimations];
}
And for completeness, in your interface (.h) file you should add;
-(void) myFirstAnimationDidStop;
#selector is easy, it's just a way of pointing to another method - hopefully this example clarifies that.
i've a problem : in my app i've a UISlider. Its function is to set the volume of some files i've included. I want to do this thing : the slider will be hide when user tap the screen and will be not hide when the user retap the screen. But there were 2 problems :
1.- i want to use a slow hide effect, not from .alpha=0.0 to .alpha=1.0, but gradually
2.- i don't know what to do if user tap the screen when slider is going to hide or to show
Sorry for my english, i'm italian :)
Thanks
Use animations
// To hide the slider slowly
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
slider.alpha = 0.0;
[UIView commitAnimations];
// To show the slider
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
slider.alpha = 1.0;
[UIView commitAnimations];
I need to show fade-in kind of transition effects while the view changes its orientation from one mode to other. Can anyone suggest me how to get that?
I would use an animation block inside of this method like so:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[UIView beginAnimations:#"InterfaceFade" context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:duration];
// Change properties to animate here (Ex: view.alpha = 0.0)
[UIView commitAnimations];
}
how can I implement the animation we see in the iPhone Music app's coverflow screen? when you click on a small view, it flips and scales up to another view? how can I do this? I can use core animation to flip and scale a view, but how can I do the transition to another view? thanks
You need an UIView as Container for the two UIViews (frontside/backside) and then remove/add these from/to the container as subviews while doing the animations in between:
UIView *flipContainer;
UIView *frontSide;
UIView *backSide;
//...
-(void)turnUp
{
[backSide removeFromSuperview];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:flipContainer cache:YES];
[UIView setAnimationDuration:1.0];
CGAffineTransform transform = CGAffineTransformMakeScale(1.2, 1.2);
flipContainer.transform = transform;
[UIView commitAnimations];
[flipContainer addSubview:frontSide];
}
-(void)turnDown
{
[frontSide removeFromSuperview];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:flipContainer cache:YES];
[UIView setAnimationDuration:1.0];
CGAffineTransform transform = CGAffineTransformMakeScale(1, 1);
flipContainer.transform = transform;
[UIView commitAnimations];
[flipContainer addSubview:backSide];
}
I'm trying the exact code you are doing - I get a zoom effect but no turn over. The only difference is that right before the turnUp code I add the flipContainer (with back showing) so then it can be flipped over.
// construct animation container
self.flipContainer = [[FlipContainer alloc] init];
[self.flipContainer.view setFrame:CGRectMake(clickedSquareX, clickedSquareY, 200, 200)];
[self.flipContainer.view addSubview:self.backside.view];
// add animation container
[self.myParentView.view addSubview:self.flipContainer.view];
// PROCEED to your turnUp code
The reason I'm doing this is I have a bunch of images in a horizontal UIScrollView and so to 'simulate' a 200x200 image flipping over and zooming to show detail I add my flipContainer with the backside showing the exact image over the exact spot of the pressed image. It should work shouldn't it? A bit confusing to me is the first line of your turnUp code you do:
[backSide removeFromSuperview];
..which would remove the view I just added.
I'm not sure if this is the right spot to put this question in - sorry if it isn't!
I have a nice and easy "zoom" animation for a view, which starts as a dot and animates up to full screen size:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
myView.frame = CGRectMake(0,0,320,480);
myView.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
So far so good :-)
The problem is that when I add subviews to myView, to my surprise, they do not follow their superview's animation scheme!?!?
Btw. subviews are currently added as usual in MyView's initWithFrame. I tried to set their transform property to CGAffineTransformIdentity bu it did not help.
So, what needs to be done to allow a subview of myView to also animate in a nice "zoom" fashion together with its superview?
Thanks in advance!
/John
I just ran in to the same problem, and the solution was surprisingly easy. Whereas modifying the frame size only affects the current view, not the subviews (as you noticed), the transform property applies to the subviews as well.
I'm trying to do the reverse of what you're doing (have a subview that appears to 'drop' on to the top of an existing view when displayed, rather than zoom from the center). This code works for me:
self.transform = CGAffineTransformMakeScale(2,2);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
self.transform = CGAffineTransformMakeScale(1,1);
self.alpha = 1.0;
[UIView commitAnimations];
Try setting self.transform to CGAffineTransformMakeScale(0,0) before beginning the animation, and set it back to (1,1) before committing. Don't modify the frame at all - leave it at the size you want the view to have after the animation completes.
You can always use the auto-sizing in the interface builder . This way you can specify the left/margin which you don't want to change and the axis along which you want the particular sub-view to resize to .