UIView animation doesn't work first time - iphone

I have a seachButton in the navigation bar which upon hitting calls following method:
- (IBAction)search:(id)sender
{
if (nil == searchViewController)
searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:nil];
searchViewController.view.backgroundColor = [UIColor clearColor];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown
forView:searchViewController.view
cache:NO];
[self.view addSubview:searchViewController.view];
[UIView commitAnimations];
}
It should load SearchViewController.xib which contains a view with UISearchBar and two buttons. When I call the search method for the first time, the view appears very quickly with some weird animation, when I call it again, the animation is alright. Does anyone have a clue what could be wrong?

Add both views to window in appdelegate, I had the same problem you had and this worked. Strange because later on I remove them from the superview but it is still working.

A UIViewController does not load its view until the view method is called. I guess the problem is the view is not loaded when you call the animation first time. You can try to modify you code like this:
if (nil == searchViewController) {
searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:nil];
searchViewController.view;
}

Try putting the animation code in the viewDidLoad function. This ensures all assets and views from the nib file have been loaded and are able to be used by your app.
- (IBAction)search:(id)sender
{
if (nil == searchViewController)
searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:nil];
[self.view addSubview:searchViewController.view];
}
-(void)viewDidLoad
{
self.view.backgroundColor = [UIColor clearColor];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown
forView:self.view
cache:NO];
[UIView commitAnimations];
}

Try putting the code for animations and view loading in the viewDidAppear: method instead of viewDidLoad: (which Chris suggested above).
In general, I have had problems doing view related things in viewDidLoad:. But doing those in viewDidAppear: has always helped (I might be missing some subtlety that causes this behavior).

Related

UINavigationController custom animation [duplicate]

I want to show a custom animation when pushing a view controller: I would like to achieve something like an "expand" animation, that means the new view expands from a given rectangle, lets say [100,100 220,380] during the animation to full screen.
Any suggestions where to start, respectively any documents, tutorials, links? :)
Alright. I could make the expand animation with the following code:
if ([coming.view superview] == nil)
[self.view addSubview:coming.view];
coming.view.frame = CGRectMake(160,160,0,0);
[UIView beginAnimations:#"frame" context:nil];
[UIView setAnimationDuration:4];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[coming viewWillAppear:YES];
[going viewWillAppear:YES];
coming.view.frame = CGRectMake(0, 0, 320, 480);
[going viewDidDisappear:YES];
[coming viewDidAppear:YES];
[UIView commitAnimations];
My View is properly displayed, but unfortunately the navigation bar is not updated. Is there a way to do that manually?
In the sample code, a function is called all 0.03 seconds that updates the transformation of the view.
Unfortunately, when pushing a UIViewController, I am not able to resize the frame of the view ... am I ?
I use the following function (added to UINavigationController) to customize the push animation:
- (void) pushController: (UIViewController*) controller
withTransition: (UIViewAnimationTransition) transition
{
[UIView beginAnimations:nil context:NULL];
[self pushViewController:controller animated:NO];
[UIView setAnimationDuration:.5];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationTransition:transition forView:self.view cache:YES];
[UIView commitAnimations];
}
I guess you could adapt this code to do whatever animation you want.
The code which you are looking for:
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:0.80];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:
UIViewAnimationTransitionFlipFromRight
forView:self.navigationController.view cache:NO];
[self.navigationController pushViewController:menu animated:YES];
[UIView commitAnimations];
What you could do is push the next view controller but don't animate it, like so:
[self.navigationController pushViewController:nextController animated:NO];
...and then, in the view controller that is getting pushed in, you could do a custom animation of it's view using CoreAnimation. This might be best done in the viewDidAppear:(BOOL)animated method.
Check out the Core Animation Guide on how to actually do the animation. Look particularly at the implicit animation.
EDIT: updated link
#zoul: That worked great! I just changed "self" to "self.navigationController" and "self.view" to "self.navigationController.view" Don't know if that was necessary, but it worked. And #crafterm, as for popping back, just make your own leftBarButtonItem by adding this code in viewDidLoad or ViewWillAppear:
//add your own left bar button
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(backButtonTapped)];
self.navigationItem.leftBarButtonItem = backButton;
[backButton release];
Then I just tweaked the push function and made this popWithTransition function that I called in my -backButtonTapped method.
- (void) popWithTransition: (UIViewAnimationTransition) transition
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.75];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationTransition:transition forView:self.navigationController.view cache:YES];
[UIView commitAnimations];
[self.navigationController popViewControllerAnimated:NO];
}
Note that the popViewController call got shifted down to the end, after the animation. Don't know if that's kosher, but again, it worked.
What you want is the downloads for chapter 2 of iphone developers cookbook. Look at the affineRotate sample specifically, although any of the core animatin samples will help you.
Have a look at ADTransitionController, a drop in replacement for UINavigationController with custom transition animations (its API matches the API of UINavigationController) that we created at Applidium.
You can use different pre-defined animations for push and pop actions such as Swipe, Fade, Cube, Carrousel and so on. In your case, the animation you are requesting is the one called Zoom.

iPhone view appearing behind animation

I have set up a multiview application with two views. The views can be switched using a button in each view (there are two separate actions). I am using the animation UIViewAnimationTransitionFlipFromRight, and when I go from the first to the second view, the view I am going to appears behind the flipping animation. I would like it just to be white. Any help is appreciated.
alt text http://img35.imageshack.us/img35/9982/picture11wu.png
This is the action switching the views:
- (IBAction)switchViewsOne:(id)sender
{
if (self.uLViewController == nil)
{
ULViewController *uLController =
[[ULViewController alloc]
initWithNibName:#"ULView"
bundle:nil];
self.uLViewController = uLController;
[uLController release];
}
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
UIViewController *comming = nil;
UIViewController *going = nil;
UIViewAnimationTransition transition;
if (uLViewController.view.superview == nil)
{
comming = uLViewController;
going = mainViewController;
transition = UIViewAnimationTransitionFlipFromLeft;
}
[UIView setAnimationTransition: transition forView:self.view
cache:YES];
[comming viewWillAppear:YES];
[going viewWillDisappear:YES];
[going.view removeFromSuperview];
[self.view insertSubview: comming.view atIndex:10];
[going viewDidDisappear:YES];
[comming viewDidAppear:YES];
[UIView commitAnimations];
}
You could try using addSubView which just adds it to the top of the stack.
This kind of bug can be if comming.view is nil
[self.view insertSubview: comming.view atIndex:10];
Check, maybe your nib isn't loaded properly
ULViewController *uLController = [[ULViewController alloc] initWithNibName:#"ULView" bundle:nil];
NSLog(#"Loaded controller %#:", uLController);

Custom Animation for Pushing a UIViewController

I want to show a custom animation when pushing a view controller: I would like to achieve something like an "expand" animation, that means the new view expands from a given rectangle, lets say [100,100 220,380] during the animation to full screen.
Any suggestions where to start, respectively any documents, tutorials, links? :)
Alright. I could make the expand animation with the following code:
if ([coming.view superview] == nil)
[self.view addSubview:coming.view];
coming.view.frame = CGRectMake(160,160,0,0);
[UIView beginAnimations:#"frame" context:nil];
[UIView setAnimationDuration:4];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[coming viewWillAppear:YES];
[going viewWillAppear:YES];
coming.view.frame = CGRectMake(0, 0, 320, 480);
[going viewDidDisappear:YES];
[coming viewDidAppear:YES];
[UIView commitAnimations];
My View is properly displayed, but unfortunately the navigation bar is not updated. Is there a way to do that manually?
In the sample code, a function is called all 0.03 seconds that updates the transformation of the view.
Unfortunately, when pushing a UIViewController, I am not able to resize the frame of the view ... am I ?
I use the following function (added to UINavigationController) to customize the push animation:
- (void) pushController: (UIViewController*) controller
withTransition: (UIViewAnimationTransition) transition
{
[UIView beginAnimations:nil context:NULL];
[self pushViewController:controller animated:NO];
[UIView setAnimationDuration:.5];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationTransition:transition forView:self.view cache:YES];
[UIView commitAnimations];
}
I guess you could adapt this code to do whatever animation you want.
The code which you are looking for:
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:0.80];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:
UIViewAnimationTransitionFlipFromRight
forView:self.navigationController.view cache:NO];
[self.navigationController pushViewController:menu animated:YES];
[UIView commitAnimations];
What you could do is push the next view controller but don't animate it, like so:
[self.navigationController pushViewController:nextController animated:NO];
...and then, in the view controller that is getting pushed in, you could do a custom animation of it's view using CoreAnimation. This might be best done in the viewDidAppear:(BOOL)animated method.
Check out the Core Animation Guide on how to actually do the animation. Look particularly at the implicit animation.
EDIT: updated link
#zoul: That worked great! I just changed "self" to "self.navigationController" and "self.view" to "self.navigationController.view" Don't know if that was necessary, but it worked. And #crafterm, as for popping back, just make your own leftBarButtonItem by adding this code in viewDidLoad or ViewWillAppear:
//add your own left bar button
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(backButtonTapped)];
self.navigationItem.leftBarButtonItem = backButton;
[backButton release];
Then I just tweaked the push function and made this popWithTransition function that I called in my -backButtonTapped method.
- (void) popWithTransition: (UIViewAnimationTransition) transition
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.75];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationTransition:transition forView:self.navigationController.view cache:YES];
[UIView commitAnimations];
[self.navigationController popViewControllerAnimated:NO];
}
Note that the popViewController call got shifted down to the end, after the animation. Don't know if that's kosher, but again, it worked.
What you want is the downloads for chapter 2 of iphone developers cookbook. Look at the affineRotate sample specifically, although any of the core animatin samples will help you.
Have a look at ADTransitionController, a drop in replacement for UINavigationController with custom transition animations (its API matches the API of UINavigationController) that we created at Applidium.
You can use different pre-defined animations for push and pop actions such as Swipe, Fade, Cube, Carrousel and so on. In your case, the animation you are requesting is the one called Zoom.

Flip View Iphone

please consider the code below, and tell me what I'm doing wrong.
I want to flip between two UIViews.
Somehow, when I flip away from the initial view, I just get the flipped view, without animation. When I flip back, the animation shows just fine.
The flips are triggered from buttons on the views themselves.
- (IBAction)showMoreInfo:(id)sender
{
UIView *moreInfo = self.flipView;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.0];
[UIView setAnimationBeginsFromCurrentState:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
UIView *parent = self.view.superview;
[self.view removeFromSuperview];
[parent addSubview:moreInfo];
[UIView commitAnimations];
}
- (IBAction)showLessInfo:(id)sender
{
UIView *lessInfo = self.view;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.0];
[UIView setAnimationBeginsFromCurrentState:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.flipView cache:YES];
UIView *parent = self.flipView.superview;
[self.flipView removeFromSuperview];
[parent addSubview:lessInfo];
[UIView commitAnimations];
}
It's probably because you aren't using a container view as the transition view. Refer to the documentation on setAnimationTransition:forView:cache:
If you want to change the appearance of a view during a transition—for example, flip from one view to another—then use a container view, an instance of UIView, as follows:
Begin an animation block.
Set the transition on the container view.
Remove the subview from the container view.
Add the new subview to the container view.
Commit the animation block.
Try using self.view.superview in the animation transition view of the showMoreInfo:
The reason the showLessInfo: method works is you are using a container view.
Can you use your MainWindow (UIWindow) as the container view as UIWindow inherence from UIView?
Also iPhone 3.0 introduced the flip transaction via the presentModalViewController method:
CustomViewController *vc = [[CustomViewController alloc]
initWithNibName:#"CustomViewController" bundle:nil];
vc.delegate = self;
// The magic statement. This will flip from right to left.
// present the modal view controller then when you dismissModalViewController
// it will transition flip from left to right. Simple and elegant.
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:vc animated:YES];
[vc release];
After iOS 4.0, you can flip between views with this:
[UIView transitionFromView:sourceView toView:destinationView duration:0.35f options:UIViewAnimationOptionTransitionFlipFromRight completion:^(BOOL finished) {
NSLog(#"I just flipped!");
}];
As Jason mentioned, you'll need this to occur within a container view.

Problem Flipping a View

I'm having some trouble getting a view to flip. I have the following code in my View Controller:
- (void)loadFlipsideViewController {
ProblemViewFlipController *viewController = [[ProblemViewFlipController alloc] initWithNibName:#"ProblemViewFlip" bundle:nil];
self.problemViewFlipController = viewController;
[viewController release];
}
- (void) flipView {
if (problemViewFlipController == nil) {
[self loadFlipsideViewController];
}
UIView *mainView = self.view;
UIView *flipView = problemViewFlipController.view;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:([mainView superview] ? UIViewAnimationTransitionFlipFromLeft : UIViewAnimationTransitionFlipFromRight) forView:self.view cache:YES];
if ([flipView superview])
{
[flipView removeFromSuperview];
[self.view addSubview:mainView];
}
else
{
[mainView removeFromSuperview];
[self.view addSubview:flipView];
}
[UIView commitAnimations];
}
The problem is, is that when I call flipView, the view is replaced with a blank view (i.e. nothing in the view I'm flipping to is displayed).
Is there something obvious I'm missing here? (I suspect there is!)
Not positive, but I think you need to use a 'controller' to flip the views. Looks like you're using one of the flipped views as the controller. Just add a root controller to flip your views.
Code like this should work from the root controller:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES]; // self.view is the root controller's view
[mainViewController viewWillAppear:YES];
[flipViewController viewWillDisappear:YES];
[flipViewController.view removeFromSuperview];
[self.view addSubview:mainViewController.view];
[flipViewController viewDidDisappear:YES];
[mainViewController viewDidAppear:YES];
[UIView commitAnimations];
Based on the variable names, it looks like this is adapted from the default "Utility" application template you get from XCode. If the template project works, and yours doesn't, then you've obviously changed something you shouldn't have :-)
Chances are, one of the outlets in your controller that should be pointing at a view, isn't. Double-check your Nibs, and check the values of the outlets in the debugger. If all else fails, start over again from the template, and see at what point it stops working.