What is the built in method which can be used to hide and show toolsbars. specifying a rate or speed of the animation?
Look at this question, and do something like:
[UIView animateWithDuration:2.0
animations:^{
[self.navigationController setToolbarHidden:YES animated:YES];
}
completion:^(BOOL finished){
// whatever
}];
Toolbar's just a view—add an IBOutlet in your controller, then use UIView's (class methods) block animation methods, such as animateWithDuration:delay:options:animations:completion: or animateWithDuration:animations:. In the animation block, just move the view.frame.size.origin.y to a different location, or set its opacity to zero. the methods also allow you to specify the time period over which the animation will occur. Once complete (there's a delegate callback in the first method), you can then ask your main view to get taller by using the same methods to change the view.frame.size.origin.y of your main view.
Related
I am relatively new to iPhone development. I have two view controllers. I want to navigate from one screen to another after 3 sec interval with fade out animation. Can anyone please provide pointers on how to proceed with this?
You don't need sleep and also you can only sleep when in background process. Seeing as you are animating, you need to do this in the main thread.
This animation will take 3 seconds and sets the view alpha to 0. i.e. fade out. Then when the animation is finished, it fires the completion block. This will push the newView.
[UIView animateWithDuration:3.0 animations:^{
[self.view setAlpha:0.0];
} completion:^(BOOL finished) {
[self.navigationController pushViewController:newView animated:YES];
}];
Use sleep to pause execution in ios then push the next view controller on your navigationcontroller.
the fade animation you can do by changing the navigationcontroller animation like explained here: http://www.davidhamrick.com/2011/12/31/Changing-the-UINavigationController-animation-style.html
Write a new method where you write your navigation code and from your button action or where you are writing the present navigation code use "performSelector: withObject: afterDelay:" method with delay of 3 and object as nil.
For UIViewControllers you can use:
transitionFromViewController:toViewController:duration:options:animations:completion:
Or transitionWithView:duration:options:animations:completion: for UIViews.
In one of my project i'm using only a UIWebView. I need an animation (for example a flip) when I reload my webView with another content... Is it possible to create a flip animation (or something similar)? I must create a fake controller to get it?
Solutions?
Thanks
You can always do the +transitionWithView:duration:options:animations:completion: method with the web view.
[UIView transitionWithView:self.webView duration:1.0 options:UIViewAnimationOptionTransitionFlipFromLeft | UIViewAnimationOptionAllowAnimatedContent animations:
^{
[self.webView loadHTMLString:#"<strong>Hello world</strong>" baseURL:nil];
} completion:^(BOOL finished)
{
}];
This method is basically a way of saying: "change the contents of this view, in animated fashion". So it takes an snapshot of the current state, performs the animation (be it a flip, curl, etc) and then inserts an snapshot of the new state.
But notice that I've used UIViewAnimationOptionAllowAnimatedContent, this forces the animation to not use a snapshot for the new state of the view, because setting loadHTMLString does not change the view immediately, so we need to force it to use the live context of the view instead of a snapshot.
The weather app in iOS (pre 7) uses a similar method for alternating between the current weather and the picker for other regions/options when clicking the "i" on the bottom.
I think that you don't need to create a controller for that. You can simply add something like that:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.80];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:yourView cache:YES];
[UIView commitAnimations];
I have multiple annotations set up on an MKMapView. Instead of using map annotation callouts when a pin is clicked, I instead want to animate a subview (self.detailView) up into the bottom of the screen, and move it back out when nothing is selected. When the user has a pin selected, and then selects another pin, I want my view to animate off screen, and then immediately animate back on screen (with different information corresponding to the newly selected annotation, of course).
Without thinking too hard, I tried what seemed like the easy thing to do - when annotation is selected, animate self.detailView onto screen, and when it is deselected, animate self.detailView off screen:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
NSLog( #"selected annotation view" );
[UIView animateWithDuration:0.2f
delay:0.0f
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
[self.detailView setFrame:CGRectMake(0, 307, 320, 60)];
}
completion:^(BOOL finished){
}];
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
NSLog( #"deselected annotation view" );
[UIView animateWithDuration:0.2f
delay:0.0f
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
[self.detailView setFrame:CGRectMake(0, 367, 320, 60)];
}
completion:^(BOOL finished){
}];
}
This works fine when no pin is selected and the user selects a pin, and when a pin is selected and the user deselects it by clicking on empty space. Of course, the problem occurs when a pin is already selected: if the user then clicks on another pin, didDeselectAnnotationView and didSelectAnnotationView are fired in rapid succession, both animations try to run at the same time, and as a result the effect doesn't work properly. Normally I would chain the animations together by putting the second animation in the completion block of the first, but since they are in separate methods I obviously can't do that here.
Anyone have any ideas on how I might be able to get around this issue? Thanks!
There may be a better way to do what you want, but I'll answer your specific question first.
Implement public methods in your controller that controls the view that animates off and on again:
- (void)showInfoView:(MyInfoClass*)theInfo;
- (void)hideInfoView;
In showInfoView you set a flag that it is shown/showing and animate it on-screen - do this code in a block and call it immediately just to get it working like this...
dispatch_block_t showBlock = ^
{
self.isShowing = YES;
/* show code goes here */
};
showBlock();
In hideInfoView you animate it off and unset the flag in the animation completion block.
Now in showInfoView before calling that showBlock check the flag to make sure it's not already shown - if it is then instead of executing the block immediately, add it to the end of an NSMutableArray called toShowBlocks. Then in hideInfoView before unsetting the flag check if the toShowBlocks array is not empty, if it's not then you remove and call the first item (using the array as a FIFO queue) like this...
dispatch_block_t nextShowBlock = [toShowBlocks objectAtIndex:0];
[toShowBlocks removeObjectAtIndex:0];
nextShowBlock();
Then you simply need to call your show and hide methods as the pins are selected/deselected and this will take care of it for you. This should set you on the right path at least.
Maybe a better way:
There are a few problems with the above, the animated view might get hidden and shown a lot if the user goes nuts pressing pins, resulting in a long-winded queue of animations before the user gets the last one. Also, views don't follow the map around like annotations do when the user pans and zooms the map. So you might be better off using custom annotations for your info view. This is a real pain because MKAnnotation views don't behave like regular UIViews and this causes all sorts of problems. However, I describe a way to use MKAnnotations as custom call-outs in this answer: https://stackoverflow.com/a/8649951/461492.
I am trying to create an animation for switching views on iOS devices.
I have create an application with three views and I have some navigation buttons.
The way I use to switch views is this:
-(IBAction) loadThirdView:(id)sender {
[self clearView];
self.thirdViewController.view.frame = CGRectMake(0, 208, 160, 208);
[self.view insertSubview:thirdViewController.view atIndex:0];
}
As you can see this is the action that takes place once I press the button. What I would like is the new view to appear in an animated way.
Specifically I want it to start from the left hand side of the screen and slide to the right. I do not want it just to appear.
Is this possible? how can I do it?
Oh no! Ah, no! Please do not display UIViewControllers this way.
Present your UIViewController this way:
[self presentModalViewController:self.thirdViewController animated:YES]
Before presenting it, you can change the modalTransitionStyle property of the view controller to suit your needs.
If using a UINavigationController, use instead:
[yourNavController pushModalViewController:self.thirdViewController animated:YES]
This is a nice little article (if not a little too harsh): Abusing UIViewControllers
To animate it the way you specifically would like (as the UINavigationController style is sliding in from the right), you might want to use something like what is proposed in this SO question: iPhone Pushing View Controller in a left direction
You can try
[UIView transitionFromView:currView toView:nextView duration:0.5f options:UIViewAnimationOptionTransitionFlipFromLeft completion:nil];
if you want different type of animation. There're lots AnimationsOptions you can choose, just set the options:.
Sample Code :
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.6];
yourImageVieew.alpha=0.9;//insert here what you want
[UIView commitAnimations];
I want to implement a simple animation based on UIView's center property. I have a simple view and I can drag it (UIView touchesMoved is overriden). The animation should fade slowly like the view is moved under it's own inertia for some time after the user releases it. But for now I want simply to move the view after touch ends. Here is the code I have in touchesEnded:
int i;
for (i=1;i<4;i++)
{
self.center = CGPointMake(10*i, 12*i);
[self setNeedsDisplay];
usleep(100000);
}
The problem is when I run this, the code is executed nicely but "UIView" changes to late. I changed usleep time and other parameters but the result is the same. It looks like all the "pending changes" in the view are performed only after the overriden touchesEnded is finished.
Is this the right way of implementing such user interface feature or should I look for some other approaches?
Thanks in advance.
If you know the final positions you want your view center to have you could do this with an animation:
[UIView animateWithDuration:20
delay:0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
youView.center = CGPointMake(newCenterX, newCenterY);
}
completion:^(BOOL finished){
}];
If that code is being run inside of touchesEnded you are blocking the main thread and that is why the animation happens all at once when its done. You will need run this loop in the background to update the view over time. When you update the UI remember to always call back to the main thread.
Some Threading Options:
performSelectorInBackground:withObject:
performSelectorOnMainThread:withObject:waitUntilDone:
Grand Central Dispatch
Threading