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];
}
Related
I want to create something like below.
RootView does not have TabBar, From the second view there should be TabBar.
What I have currently done is, I am using UINavigationController as controller calass
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIViewController *rootController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
navigationController = [[UINavigationController alloc] initWithRootViewController:rootController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
But how can I use UITabBar with tabBarController from SecondViewController?
create the objects of the second view and then push your view with the tabbarcontroller
From Storyboard embed your SecondViewController in TabBar. Select your controller and go to Editor -> Embed in -> TabBar Controller! I'm from my mobile..sorry if i have any mispells!
You need to push your Tabbar controller's object. Initialize your tab bar controller's object and add all other controller objects to the tabbar controller's viewcontroller array.
On button action:-
1> Initialize tab bar controller and suppose you name its object as objTab;
2> objTab.viewcontrollers = [NSArray arrayWithObjects:..] ---> Objects of all viewcontrollers that are a part of your tab bar controller. Thus all objects need to be created first.
3> self.navigationcontroller pushViewController: objTAb
Something like this should do the trick (not using ARC):
//vc1, vc2, vc3 = your view controllers
NSArray *viewControllersArray = [NSArray arrayWithObjects:vc1,vc2,vc3, nil];
UITabBarController *tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:viewControllersArray];
[self.navigationController pushViewController:tabBarController animated:YES];
[tabBarController release];
What you want to do is create the UITabBarController and push that along the navigation stack.
For Sample Write loadnewview method at appdelegate .Use buttonPressed method for button action or any object action of first view controller as shown below to display tab bar from second view controller.
I have taken two tabs for sample so I wrote Capacity as 2. You can take up to 5.
-(IBAction)buttonPressed:(id)sender
{
HomeViewController *homeVC=[[HomeViewController alloc]initWithNibName:#"HomeViewController" bundle:nil];
[self.navigationController pushViewController:homeVC animated:YES];
[appDelegate loadnewview];
}
-(void)loadnewview
{
if(!self.tabBarController)
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.delegate=self;
NSMutableArray *localcontrollerarray = [[NSMutableArray alloc] initWithCapacity:2];
UIViewController *viewController1 = [[HomeViewController alloc] initWithNibName:#"HomeViewController" bundle:nil];
UINavigationController *navi1 = [[UINavigationController alloc] initWithRootViewController:viewController1];
[localcontrollerarray addObject:navi1];
UIViewController *viewController2 = [[ScanViewController alloc] initWithNibName:#"ScanViewController" bundle:nil];
UINavigationController *navi2 = [[UINavigationController alloc] initWithRootViewController:viewController2];
[localcontrollerarray addObject:navi2];
self.tabBarController.viewControllers = localcontrollerarray;
[self.window addSubview:self.tabBarController.view];
}
use this type of method in AppDelegate.m and property-synthesize UITabBarController and store array of viewcontroller in it also in application didFinishLaunchingWithOptions method just assign navigationViewController as a RootViewController like bellow..
RootViewController *masterViewController = [[[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil] autorelease];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
after then when you want to add TabBar to any view at that time call this bellow method like this..
[appDelegate addTabBarControllerInwindow];
-(void)addTabBarControllerInwindow
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.window cache:YES];
[self.navigationController.view removeFromSuperview];
[self.window addSubview:[tabBarController view]];//tabBarController.view
[UIView commitAnimations];
}
Create an Application using Tab Bar Controller and on the ViewDidLoad method of the view controller for which you want to hide the tab bar use code:
[self.tabBarController.tabBar setHidden:YES];
And don't forget to unhide the tab bar using the same code replacing NO instead of YES for the view controller for which you want to show the tab bar.
I am new to iPhone developer,
I have 4 page in my Application, my Application is viewBasedApplication.
I made my 1st page(LicAppViewController) as RootViewController, here is my code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.viewController = [[[LicAppViewController alloc] initWithNibName:#"LicAppViewController" bundle:nil] autorelease];
UINavigationController *navigationController=[[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
on button click i am navigation to 2nd page(PlanPage)
-(void)btnClicked{
PlanPage *viewController = [[PlanPage alloc]initWithNibName:#"PlanPage" bundle:nil];
[UIView beginAnimations:#"Flip" context:nil];
[UIView setAnimationDuration:0.7];
[UIView setAnimationCurve:UIViewAnimationOptionCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
[self.navigationController pushViewController:viewController animated:YES];
[UIView commitAnimations];
[viewController release];
}
till now it is working fine, but when i select a row in 2nd page it crashes my application, i want to navigate to 3rd page(DetailPlanPage), here is my code
DetailPlanPage *nextController = [[DetailPlanPage alloc] initWithNibName:#"DetailPlanPage" bundle:nil];
[self.navigationController presentModalViewController:nextController animated:TRUE];
but when i write, this line:
[self.navigationController pushViewController:nextController animated:YES];
instead of:
[self.navigationController presentModalViewController:nextController animated:TRUE];
it's working fine. (I am not sure but crash of my application may be because of viewBased Application)
Thanks In Advance !
set rootview controller first
remove that code
[self.window addSubview:navigationController.view];
and include
self.window.rootViewController = navigationController;
in present modal view controller u can try like this
yourview *detailViewController = [[yourview alloc] initWithNibName:#"yourview" bundle:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc ] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(dismiss)];
detailViewController.navigationItem.leftBarButtonItem = doneButton;
UINavigationController *nav;
nav=[[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
[self presentModalViewController:nav animated:YES];
[detailViewController release];
[doneButton release];
-(void) dismiss
{
[self dismissModalViewControllerAnimated:YES];
}
Try
[self presentModalViewController:nextController animated:YES];
you would also want to set the delegate for nextController to self and add a delegate function to dismiss Modal View Controller.
The most important difference is about semantics. Modal view controllers typically indicate that the user has to provide some information or do something. This link explains it more in depth:
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html
When you present a modal view controller, the system creates a parent-child relationship between the view controller that did the presenting and the view controller that was presented. Specifically, the view controller that did the presenting updates its modalViewController property to point to its presented (child) view controller. Similarly, the presented view controller updates its parentViewController property to point back to the view controller that presented it. And also another link.
I am wanting to animate my view change, however I am not sure where to put my animation since I have a UITabBarController controlling which view I am on and what I can switch too.. This is being declared in my appdelegate.m file as per the xcode template.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
Or their is the area in each viewcontroller where everything gets loaded... Im thinking it might be better to initialize the animation in here.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Super", #"Super");
self.tabBarItem.image = [UIImage imageNamed:#"SuperIcon"];
}
return self;
}
As I have not done alot of animation with views before I am woundering where I could declare this peice of code that will hopefully animate my view change when a UITabBarButton is touched....
[UIView transitionWithView:containerView
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ [fromView removeFromSuperview]; [containerView addSubview:toView];
completion:NULL];
or have I missed the boat completely and is their somewhere else I should be doing this?
Try the following code in the viewWillAppear method
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.4];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft
forView:self.view cache:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView commitAnimations];
This worked for me for a tabBar controller based app.
Try that animation in code in viewWillAppear method
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 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