I am new to the objective c coding in iPhone. i am using below code in separate function to start the animation.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:10.0];
object.transform = CGAffineTransformMakeRotation(1.57);
[UIView commitAnimations];
After this i am trying to restart the animation in one more separate function, before the time (10 sec that is mentioned in above).
So the thing is if i want to restart the animation in another function(but in the same .m file)once again at 5th sec. So please tell me how to solve this issue.
If you start a new animation while one is already in process for the same property/ies it should start animating to the new property values from whatever the current values are, using the new animation settings.
So when you say you want to reset the animation, do you mean you want it to go back to the start, or just do something different? If the former I believe you'll just need to set the property/ies (in this case your transform) back to its initial settings and start a new animation block.
Related
I am developing an application which needs to decrease the width of imageview to 0 from 320 in a 1hour time. for this i am using following code
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:3600];
newRect.size.width = 0;
imgView.frame = newRect;
[UIView commitAnimations];
it is works fine if we stay in same view controller,after animation starts if the user navigate to some other viewcontoller, How to handle the animation.
Along with this i have one more issue- during the animation the image in imageview is looks like shrink as throughout the animation i am using same image ,So i want to change the image in imageView during the animation How can i achieve this.
Is there any other way to do this apart form the animation.
Any Help is Appreciated.
The life cycle of the controllers and views will not allow you to do this so simply. The objects you are using can and will be deallocated by the system if they are not currently needed anymore, so the animation you started is essentially discarded with it.
You will have to store the progress of your animation somewhere, e. g. in a file or a CoreData database to have it persistent across the instantiations of that view. Depending on the exact situation, it might be sufficient to store the start time of the animation once it begins. Then, in viewWillAppear you could load it and calculate how much progress into that one hour has been made and start a new animation from that point. To the user it would appear as if the animation had proceeded in the background.
In iOS (version 5 is fine), I have a custom animation to flip and zoom an image transitioning from one UIViewController to another using:
TCFlipZoomSubviewSegue segue=[[TCFlipZoomSubviewSegue alloc] initWithIdentifier:#"SegueToMenuTable" source:self.iViewController destination:self.mViewController];
[segue perform];
and in the perform method I have:
[UIView animateWithDuration:3.75f
delay:0.0f
options:UIViewAnimationOptionAllowAnimatedContent
animations:^{
self.subviewTransformView.layer.transform=transform;
} completion:^(BOOL finished) {
[destination.parentViewController.view bringSubviewToFront:destination.view];
}
It all works fine, but all sorts of problems occur (layout is messed up) if I rotate the device during the animation. What I want is for the animation to complete before the orientation event occurs - which is the standard behaviour in iPhones - eg try rotating the MAIL app immediately after clicking INBOX - it completes the slide transition then rotates. Same with the Stocks app etc. And that's what happens if I use a standard Push animation etc. But I have my own animation to do.
So how do they do that?
How do I prevent (ie delay, or block) the orientation change until my animation finishes? I can easily stop the change by saying NO in shouldAutorotateToInterfaceOrientation: when I'm animating but then i need it to do the orientation after. I could call attemptRotationToDeviceOrientation but surely there must be a better way - The segue itself should be able to complete without being interrupted.
I think the way you mentioned is probably the way you have to do it -- that is, return NO to shouldAutorotateToInterfaceOrientation:, and then call attemptRotationToDeviceOrientation when your animation is done. You would probably need some sort of flag that is set if the user tries to rotate while the animation is in progress, so you would know whether you should call attemptRotationToDeviceOrientation when the animation finishes.
I am using a UIScrollView with a list of buttons made to look much like a UIPickerView. I have just implemented shake to shuffle, where upon detection of a shake I set the content offset of the UIScrollView to the position of the randomShuffle using the following.
[Singlescroll setContentOffset:CGPointMake(jumpX, jumpY+randShuffle*sepValue) animated:YES];
Instead of just moving the content offset to the random position that matches a button I would like to implement a shuffle animation where the view almost 'spins' like a slot machine and then ends up on the randomShuffle button position.
I tried to do this by simply animating the offset to the top of the UIScrollView then back down again before going back to the randomShuffle position (one after another), however this didn't work and it just went straight to the randomShuffle position. I realise that I didn't try this with a timer so the animations were not delayed however I would like to avoid running a timer if possible.
Is there any inbuilt animations that can handle this? and if not please can you suggest how I might approach this before using timers? thank you.
Instead of just using animated:YES, did you try putting it into something like:
[UIView animateWithDuration:.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
[Singlescroll setContentOffset:maximumOffsetPoint]; //spin all the way up?
}completion:^(BOOL finished){
if (finished)
//kick off another animation, to spin it back down:
[UIView animateWithDuration:.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
[Singlescroll setContentOffset:CGPointMake(jumpX, jumpY+randShuffle*sepValue)];
}completion:nil];
}
}];
I don't know if this answers your question, but completion blocks are super handy and might be what you need. Within the completion block, the second animation will only get called at the end of the first animation.
Also, there are several animateWithDuration: methods on UIView, but in my experience this one is more reliable for animating properties such as contentOffset and zoomToRect of scroll views.
I have a question regarding Xcode.
I found a tutorial on the net that allowed me to move an image around the screen.
Could you please explain how I can make my button move to the left and back to right with one click (I can't find this anywhere...), and immediately after that run another IBAction that allows me to switch to another subview? (I already have this code naturally...). I tried to add both IBActions in 1 centralized one, but it didn't seem to work :-( It opens in this case immediately the subview without showing me the animation.
What I tried:
The code obtained until now:
-(IBAction) aMove: (id) sender{
if (bMove == NO) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
btnTarget.transform = CGAffineTransformMakeTranslation(-30,0);
[UIView commitAnimations];
bMove = YES;
}else{
btnTarget.transform = CGAffineTransformIdentity;
bMove = NO;
}
}
-(IBAction) aAnimateActivate: (id) sender {
[self aMove:nil];
[self targetOpenView:nil]; //Opens the subview
}
I appreciate your help! Thanks!
concatenate works to combine animations and I just put two blocks of animations (two of the one shown below) after each other... :
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
CGAffineTransform transform = CGAffineTransformConcat(CGAffineTransformMakeScale(1, 1),CGAffineTransformMakeTranslation(10, -50));
btnGuide.transform = transform;
[btnGuide setAlpha:0.0];
[UIView commitAnimations];
Basically implementing this code did the trick... Easy!
However... I needed some additional pieces of code for the further implementation such as:
[self performSelector:#selector(aGuide) withObject:self afterDelay:0.0];
(don't mind the selector name)
and:
[NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:#selector(targetOpenView:) userInfo:nil repeats:NO];
Without looking at all of your program flow nor doing any actual testing (and I find when using Core Animation that the only way to be sure it works right is to code it and see if it does) the problem with the subview opening right away occurs because right after you invoke your "aMove" method to set up the first animation the thread continues with the next line of code, i.e., the [self] targetOpenView:nil statement, which immediately opens the subview and thus doesn't allow the first animation sequence to be shown. There is no pause to wait for the first animation to be completed. The animation, once commited, runs on its own thread while your code continues to run on the current thread (probably the application's main thread). That might not seem to be the most sensible way but you have to think of the code you write as the process to set up an animation that, once committed, is a separate entity that is free to run on its own (beside your code). The advantage to Apple's implementation is that you can set up a whole bunch of different animations which occur at the same time. One of Core Animation's design goals is to take away the need for the programmer to be handling all the starting and stopping of various animations and instead let the animation coordination be done using various methods of delay and duration or providing the means for one animations events to be observed (and acted upon) by other animations.
In order to do the animation(s) the way you want you will need use a method which only allows the second animation to begin once the first is over. One way (assuming that the subview change would be set up as an animation itself) is to use a completion: handler, an animation block that only begins upon completion of the first animation. Another way is to let the two animations "start together" but include a delay: parameter in the second animation that is equal to the length of the first animation. If the subview change is not done with an animation but is just done with code in the main thread then you need to set up a an animation delegate that is called when certain events occur in your animation, one of which is it's completion. Parameter(s) are passed to your delegate to tell you what is occurring and to which animation.
All of this is discussed, with examples, in the Animations section of the View Programming Guide to iOS (about 10 pages that will probably show you almost exactly how to do what you want):
http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/AnimatingViews/AnimatingViews.html#//apple_ref/doc/uid/TP40009503-CH6
Also, in order to set up the first animation to move the button somewhere and back again you might want to read the subtopic in that same section of the guide mentioned above: Implementing Animations That Reverse Themselves. I think it would be the cleanest way to do what you want.
(FYI, I'm better with the MacOS side of Core Animation than the iOS side but the "why did this happen immediately?" problem you have is a common pitfall when getting up to speed with how it works. Hope this explanation helps.)
I've scoured blogs and Apple documentation and can't find an answer. Hope someone can lend their expertise.
I have a simple UIView animation that acts upon a container view 'gameContainer'. If I create this container view in a method called previously, all is well and good.
However, when I create 'gameContainer' immediately prior to the animation calls (code below) then the subView 'viewGrid' just appears without any animation effect.
-(IBAction) onInfoUp: (id) sender {
//Add a container UIView for animation
[self.view addSubview:gameContainer]; // Moving this line to 'viewDidLoad' cures problem
//Call animation methods
[UIView beginAnimations:#"newGrid" context:nil];
[UIView setAnimationDuration:1.3];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft
forView:gameContainer cache:YES];
[gameContainer addSubview:viewGrid];
[UIView commitAnimations];
}
I'm stumped as to why I must define the subview container in a separate method! Thanks in advance.
I believe this is due how UIKit updates the visual contents on the screen. All actual modifications to the screen happens at the end of the current run loop if it's running on the main thread, or at the end of the next run loop on the main thread otherwise. If you add gameContainer as shown in the code, it's not on the representation layer for the screen.