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.
Related
Anybody have any idea how this is done?
http://youtu.be/r_cII4_aq_A
In general, the idea is awesome, but I would like to know how to do each specific thing. In the video, the pages are being swiped too fast so you can't see, but as you transition from one page to the next, each pixel smoothly transitions to it's new color. Also, it's really cool how the icon gets smaller to a minimum size as you transition away from a screen.
Maybe there's some 3rd party library that provides a protocol and it's relatively easy to implement, but I can't find it. If there's not, I'm thinking it's just one view controller with many views side by side and as you drag your finger, it calculates where each view needs to be..and what color every pixel needs to be.
I imagine you already have it by now. But in case you still have any doubts, I made gist that does the animation: https://gist.github.com/mnmaraes/9536364
Anyways, have fun.
It's a fade animation, so:
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
_backgroundImageView.image = nextImage;
} completion:nil];
should do the trick for the background part.
For the foreground/icon part you can animate the transform to scale and translate the views as they slide in and out.
UI animations are great, very easy to use, and are used allot. The only one problem I have with it is that while the animation is moving, the view in not receiving any user interaction.
For example, if a have a UIButton that animates every time it's shown, but the user will not be able to click on it until the animation is over.
//This is a UIButton:
- (void)animationApear
{
CGRect frameSelf = self.frame;
frameSelf.origin.y -= frameSelf.size.height;
[UIView animateWithDuration:1.0 delay:0
usingSpringWithDamping:0.8 initialSpringVelocity:0
options:0
animations:^{
[self setFrame:frameSelf];
} completion:nil];
}
Is there any way to deal with this issue?
Thanks!
You need to supply the option UIViewAnimationOptionAllowUserInteraction.
Also, depending on your view architecture, if the button is within the animated view, or a subview thereof, then the actual location of the button isn't moving. Only the presentation layer of the button is moving, so that is why the button may not be receiving taps. A good test is to tap where the button was when the animation started (and make sure the option UIViewAnimationOptionAllowUserInteraction is on) to see if it is still receiving taps.
On solution, when you actually need to animate buttons, is to make repeated short transforms (CGAffineTransforms, for example) and have those movements in aggregate, create the visual effect of the animation. Though in this case the button itself will move, rather than simply it's presentation.
I've built a UIControl subclass to display a 1-month calendar view on
an iPhone. Most months require 5 weeks to display the dates, but
some months need 6, so I've built the control to dynamically resize
itself as needed. I'm using UIView animation to change the frame of
the control here.
The problem is, I now need the other controls on the screen to
move/resize when the calendar changes size. And I really need that
to happen with the animation of the calendar control changing size.
Ideally, I'd do this without coding a bunch of details in my calendar
control about other controls on the screen.
What's the best strategy here? I was hoping I could somehow anchor
the other controls to the frame of the calendar control and have the
platform adjust their location/size as it animates the frame change.
But, thus far, I can't find any combination of struts and springs to
make that happen.
Do I just need to bite the bullet and add my other on-screen controls
to the animation happening inside my calendar control?
I'll be interested to see if there are better answers to this.
At this point, all I know to do is override setFrame on your calendar view and when it changes, send setNeedsLayout to its superview.
But I'm not sure if standard views will autoresize this correctly. Generally geometry flows down the view tree, not up, and you want it to do both.
You may have to implement layoutSubviews on the containing view.
Move the animation logic out of the specific view and into a view controller that manages all of the controls. The view can still figure out its own proper size, and let the view controller ask. For instance:
[self.calendarView setDate:date];
CGSize calendarSize = [self.calendarView sizeForDate:date];
[UIView animateWithDuration:...
animations:^{
... re-layout everything, including the calendarView ...
}];
Another, similar approach:
[self.calendarView setDate:date];
[UIView animateWithDuration:...
animations:^{
[self.calendarView sizeToFit];
... re-layout everything else ...
}];
There are lots of similar approaches based on your preferences. But the key is to move the logic out of the specific view. Usually a view controller is the best solution. If the controls make a logical collection that could go into a single UIView, then you could have that "collection" UIView manage the same thing in its layoutSubviews, but it's more common that a view controller is a better solution here.
Thanks for the help. I tried both of these approaches with success. The override of setFrame and implementation of layoutSubviews worked, but the other controls jumped to their new locations rather than animating to those locations as the calendar control grew.
The approach of moving the other controls during the animation is what I had to go with. However, I wanted to keep the logic of the control pretty self-contained for re-use, so I left the animation in the control but added a delegate to react to size change, and put the delegate call inside the animation block. In full disclosure, I am also animating the new month's calendar onto the control while I'm growing the control, and this way I could do both of those things in the animation block.
So, the end code looks something like this:
// inside the calendar control:
[UIView animateWithDuration:0.5 animations:^{
self.frame = newOverallFrame; // animate the growth of the control
_offScreenCalendar.frame = newOnScreenFrame; // animate new month on screen
_onScreenCalendar.frame = newOffScreenFrame; // animate old month off screen
if (self.delegate)
{
[self.delegate handleCalendarControlSizeChange:newOverallFrame]; // animate other controls per the delegate
}
}];
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 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.