I have an app that has a centre view with two views off to each side of it. I want to have two navigation bar buttons, left and right which push a new navigation controller onto the view from the left or the right.
When you change views by pushing a new view using the pushviewController: method of NavigationController, the view appears to slide in from the right. how do i change this to slide in from the left?
I have done change animation direction when we push viewcontroller.
you can change animation type here [animation setSubtype:kCATransitionFromRight];
ViewController *elementController = [[ViewController alloc] init];
// set the element for the controller
ViewController.element = element;
// push the element view controller onto the navigation stack to display it
CATransition *animation = [CATransition animation];
[[self navigationController] pushViewController:elementController animated:NO];
[animation setDuration:0.45];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromRight];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
[[elementController.view layer] addAnimation:animation forKey:#"SwitchToView1"];
[elementController release];
Instead of using a navigation controller, I would just move the view.
CGRect inFrame = [currentView frame];
CGRect outFrame = firstFrame;
outFrame.origin.x -= inFrame.size.width;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[newView setFrame:inFrame];
currentView setFrame:outFrame];
[UIView commitAnimations];
I don't think you can explicitly define sliding direction in UINavigationControllers. What you might be able to do is pop the current view off the navigation stack to show the prior view, which would animate in the manner you want. However this may be complex if you want to have different view controllers appear depending on what you do on the current view.
If your workflow is not too complicated, you can hold a reference to the prior view controller in the current view controller. depending on what you do on the current view (like select a table view cell), you can change whatever data you need in the prior view controller, and then call
[self.navigationController popViewController];
or whatever the correct method is (i think that's pretty close to how it is). that would let you move down the nav stack with the animation you want, which works if your nav stack has a set number of views on it.
to what Reed Olsen said: you must only hook up one button, that starts the slide up to the same method and add a BOOL that tracks if the view is shown or not. all you need to do is set the origin properly.
- (IBAction)slideMenuView
{
CGRect inFrame = [self.view frame];
CGRect outFrame = self.view.frame;
if (self.viewisHidden) {
outFrame.origin.x += inFrame.size.width-50;
self.viewisHidden = NO;
} else {
outFrame.origin.x -= inFrame.size.width-50;
self.viewisHidden = YES;
}
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[self.menuView setFrame:inFrame];
[self.view setFrame:outFrame];
[UIView commitAnimations];
}
To get the "pointy" type button you need to use a different method.
In your AppDelegate:
UITableViewController *first = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
UITableViewController *second = [[SomeOtherViewController alloc] initWithStyle:UITableViewStylePlain];
NSArray *stack = [NSArray arrayWithObjects: first, second, nil];
UINavigationController *nav = [[UINavigationController alloc] init];
[nav setViewControllers:stack animated:NO];
You can inherit RTLNavigationController:UINavigationController and overwrite these functions.
- (void) pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
DummyViewController*dvc = [[DummyViewController alloc] init];
[super pushViewController:viewController animated:NO];
[super pushViewController:dvc animated:NO];
[dvc release];
[super popViewControllerAnimated:YES];
}
and
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
UIViewController *firstViewController = [super popViewControllerAnimated:NO];
UIViewController *viewController = [super popViewControllerAnimated:NO];
[super pushViewController:viewController animated:animated];
return firstViewController;
}
And in application delegate:
navCon = [[RTLNavigationController alloc] init];
rootViewController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
rootViewController.contextDelegate = self;
DummyViewController *dvc = [[DummyViewController alloc]init];
[navCon pushViewController:dvc animated:NO];
[dvc release];
[navCon pushViewController:rootViewController animated:NO];
[self.window addSubview:navCon.view];
Pushing will be from left to right and popping from right to left
Related
I am trying to switch views, but I want the animation with the view lifts up and its like a piece of paper folding to see what is underneath.
Any tutorials or examples of how to get that view animation, if it is an animation, would be appreciated.
Actually the view that the maps app uses when you hit the button on the corner.
Something like this should work:
MyViewController *myView = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
myView.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissModalViewControllerAnimated:)] autorelease];
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:myView];
navigation.modalTransitionStyle = UIModalTransitionStylePartialCurl;
navigation.delegate = self;
[self presentModalViewController:navigation animated:YES];
The key here is the modalTransitionStyle property needs to be set to UIModalTransitionStylePartialCurl before presenting the modal view.
More info here: UIViewController Class Reference (look for modalPresentationStyle, modalTransitionStyle, presentModalViewController:animated:, and dismissModalViewControllerAnimated:).
There are two basic ways of doing this, the old one which is no longer recommended:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown
forView:containerView cache:YES];
[containerView addSubview:subview];
[UIView commitAnimations];
And the new one (It uses blocks which are supported from iOS 4 and on):
[UIView transitionWithView:containerView duration:0.5
options:UIViewAnimationOptionTransitionCurlDown
animations:^ { [containerView addSubview:subview]; }
completion:nil];
I have a UIViewController, a "switcher" that will basically just rotate a view from one to another.
It all works great, except that the view that I am transitioning to is a UIViewController which holds a UITableViewController. For some reason, when the animation "flips", the navigation bar is invisible, and once the animation completes the navigation bar just appears.
It really doesn't look good and I was wondering if anyone knew why I might be seeing this and how I could fix it?
Thanks,
--d
EDIT: Adding some code by request!
Switcher viewDidLoad method - Currently Initializing both of the ViewControllers because I thought it may help
[super viewDidLoad];
LogoView *logoController = [[LogoView alloc] init];
self.logoView = logoController;
[self.view insertSubview:logoView.view atIndex:0];
[logoController release];
MainController *vController = [[MainController alloc] init];
self.controller = vController;
[vController release];
switchTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(switchViews) userInfo:nil repeats:NO];
Switcher switchViews method
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
if (self.controller.view.superview == nil)
{
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[controller viewWillAppear:YES];
[logoView viewWillDisappear:YES];
[logoView.view removeFromSuperview];
[self.view insertSubview:controller.view atIndex:0];
[logoView viewDidDisappear:YES];
[controller viewDidAppear:YES];
}
[UIView commitAnimations];
MainController viewDidLoad method
CGRect frame = CGRectMake(0, 0, 320, 410);
FirstLevelController *controller = [[FirstLevelController alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:controller];
navController.view.frame = frame;
navController.navigationBar.tintColor = [UIColor blackColor];
[controller release];
[self.view addSubview:navController.view];
Inside the FirstLevelController I just add the items to the table view... I've tried adding a navController.title = #"Home", but I am not even seeing the black navbar without text... it's just a big empty space.
Help is muchly appreciated!
Hah! I changed the animation "cache" from YES to NO, and it fixed it! Yay!
I have two views: one has just a button (view 1) and the other contains a tableview with a search bar (screen2). When the user clicks that button in view 1, I want view 1 to flip and display screen 2.
View 2 resides inside of the navigational controller with a navigation bar on top.
Below is what I have for now. The transition animation works and flips to the second screen but view 2 is missing the SearchBar and title from NavigationBar. Both are set inside view 2.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
navigationController = [[UINavigationController alloc] init];
bestbuyProducts = [[BestBuyProductsViewController alloc] initWithNibName:#"BestBuyProductsViewController" bundle:nil];
[navigationController pushViewController:bestbuyProducts animated:NO];
[navigationController.view setFrame: [self.view bounds]];
[bestbuyProducts release];
[self.view addSubview:navigationController.view];
[UIView commitAnimations];
Thank you
To start your UINavigationController is not initialise correctly. Use the initWithRootViewController: method like that:
bestbuyProducts = [[BestBuyProductsViewController alloc] initWithNibName:#"BestBuyProductsViewController" bundle:nil];
// Initialise the navigation view with the bestbuyProducts view controller
navigationController = [[UINavigationController alloc] initWithRootViewController:bestbuyProducts ];
Then try to use modal view transition to make a flip animation, It's easier and more safe to start:
[navigationController setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[bestbuyProducts release];
OK here is the correct version
navigationController = [[UINavigationController alloc] initWithRootViewController:bestbuyProducts];
[bestbuyProducts setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentModalViewController:navigationController animated:YES];
I build my first iPhone application and I have a problem with switching views.
First, I have two views (login, registration) which switch via "presentModalViewController:animated:".
But if someone logged in, there must be a new kind of view. I wanna have an UITabBar at the bottom (tab bar controller). But this does not work. I tried to create a new AppDelegate, so that I can use tutorials like this one which need a AppDelegate:
http://www.youtube.com/watch?v=LBnPfAtswgw&feature=player_embedded
The switch to the new controller is done like this:
startViewController = [[StartViewController alloc] initWithNibName:#"StartView" bundle:nil];
[UIView beginAnimations:#"View Curl" context:nil];
[UIView setAnimationDuration:2.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
[self.view addSubview:startViewController.view];
[UIView commitAnimations];
The screen is white, because the shown view is the UIView in my StartView.xib. There I have the new AppDelegate, File's owner, View, TabBarController. But only the UIView is loaded and not the TabBarController.
Do you have an idea how I could this problem?
Thanks & Best Regards.
I might suggest you start with a TabBarController, and if the username/password is not set, the active ViewController executes presentModalViewController:animated: to display the login/registration viewsControllers in modal mode (hidding the underliying TabBarController).
Here is some sample code for doing it programmatically.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
[window setBackgroundColor:[UIColor whiteColor]];
tabBarController = [[UITabBarController alloc] init];
aViewController = [[aViewController alloc] init];
UINavigationController *aNavController = [[[UINavigationController alloc] initWithRootViewController:aViewController] autorelease];
aNavController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
[aViewController release];
tabBarController.viewControllers = [NSArray arrayWithObjects: aNavController, nil];
// Add the tab bar controller's current view as a subview of the window
[window addSubview:tabBarController.view];
if(userNotLoggedIn){
[self displayLoginViewController];
}
[window makeKeyAndVisible];
}
- (void)displayLoginViewController {
LoginViewController *controller = [[LoginViewController alloc] init];
// setup controller
[self.tabBarController presentModalViewController:controller animated:NO];
[controller release];
}
I'm currently displaying a UIViewController like this:
[[self navigationController] presentModalViewController:modalViewController animated:YES];
and hiding it like this:
[self.navigationController dismissModalViewControllerAnimated:YES];
The animation is "slide up from the bottom"... then slide back down. How can I change the animation style? Can I made it fade in/out?
Cheers!
For iPhone 3.0+, a basic crossfade is easiest to do like this:
modalViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[[self navigationController] presentModalViewController:modalViewController
animated:YES];
Marcus Zarra posted a great solution to this on the SDK mailing list:
UIViewController *controller = [[[MyViewController alloc] init] autorelease];
UIViewAnimationTransition trans = UIViewAnimationTransitionCurlUp;
[UIView beginAnimations: nil context: nil];
[UIView setAnimationTransition: trans forView: [self window] cache: YES];
[navController presentModalViewController: controller animated: NO];
[UIView commitAnimations];
There are transitions for flipping and page-curling. If you are set on fading, can try adjusting your new view's alpha:
UIViewController *controller = [[[MyViewController alloc] init] autorelease];
controller.view.alpha = 0.0;
[navController presentModalViewController: controller animated: NO];
[UIView beginAnimations: nil context: nil];
controller.view.alpha = 1.0;
[UIView commitAnimations];
However, what you probably want is a crossfade, or at least a fade-over. When the UINavigationController switches to a new view, it removes the old one. For this effect, you're probably better off just adding a new view to your existing UIViewController and fading its alpha in over time.
Note: If you are not in your app delegate [self window] will not work. Use self.view.window , thanks to user412500's post for pointing this out.
To update for alpha fading in iOS 4:
modalController.view.alpha = 0.0;
[self.view.window.rootViewController presentModalViewController:modalController animated:NO];
[UIView animateWithDuration:0.5
animations:^{modalController.view.alpha = 1.0;}];
It should be [self.view.window] in order for the code to work
(at least that's the way that it is in ios 3.2)