How can i create a global navigation stack? - iphone

I want a global navigation stack. When the user changes tabs or navigates to a new view in the same tab, I want to push the new view onto the global navigation stack. I want the back button in the navigation bar to go back to the previous view, which is sometimes a different tab, and sometimes a different view in the same tab.

To achieve this effect, you could ditch the UITabBarController - and emulate the bar by using a custom view or customizing the standard UIToolbar.
Have one navigation controller with, with your customized toolbar always visible, and when buttons are tapped on it, just push the views you want onto the navstack.

You want all the UIViewController's in the UITabBarController to be loaded into the same UINavigationController?
So something like this:
___ RootViewController ___
| |
UINavigationController UITabBarViewController
instead of
RootViewController
|
_________ UITabbarViewController _____________________
| | |
UINavigationController UINavigationController UINavigationController
You should try "experimenting" with your own custom UITabBar

I suggest you to create a global array (NSMutableArray) that will hold NSInvocation objects. So every time you push view controller you need to create NSInvocation with navigation controller as target and popViewConrollerAnimated: as selector. If you're tapping the tab bar item you need to set tab bar controller as target and setSelectedViewController: as selector. You should also specify current view controller as parameter using
- (void)setArgument:(void *)buffer atIndex:(NSInteger)index
Then every time you pop your global stack you need just call [myLastInvocation invoke];

I Had similar issue. I did it like this :
To change the tab, use : say, you want to go at tab 2 and its 3rd view controller
self.tabBarController.selectedIndex = 2;
[self.tabBarController.delegate tabBarController:self.tabBarController didSelectViewController:
[[[self.tabBarController.viewControllers objectAtIndex:2] viewControllers] objectAtIndex:3]];

you could achieve the same by setting the left bar button of your UINavigationController as the button of your choice, Handle the action method and invoke the appropriate tabbar button on click event.
You need to do all that in your root view controller ...
ADDED:
You could not get the back button on the root view controllers (Navigation controllers;s root view associated with your tabbar instance) just by pressing the tabbar button.
you need to find the way to achieve this as you are not getting this from iOS So The movement you press the tabbar button your need to have the variable that store the previous selected index and a method that give the information for any tabbar by just passing the index ... So by using these two you could set the title of your left bar button of navigation bar and return to the previous tab by assigning the appropriate action method to the left bar button ...

I got it working. In my experience I was needed to have mainTabBarController and detailedNavigationController as two root controllers.
Those two methods of UIApplicationDelegate class work perfect:
- (void) showDetailedTab
{
CGRect normalRect = self.window.bounds;
CGRect rightRect = CGRectOffset(normalRect, normalRect.size.width, 0);
CGRect leftRect = CGRectOffset(normalRect, -normalRect.size.width, 0);
detailedNavigationController.view.frame = rightRect;
mainTabBarController.view.frame = normalRect;
[self.window addSubview:mainTabBarController.view];
[self.window addSubview:detailedNavigationController.view];
[UIView animateWithDuration:0.35 delay:0.0 options:UIViewAnimationCurveEaseOut
animations: ^{
detailedNavigationController.view.frame = normalRect;
mainTabBarController.view.frame = leftRect;
}
completion: ^(BOOL finished){
[mainTabBarController.view removeFromSuperview];
}];
}
- (void) showMainTabBar
{
CGRect normalRect = self.window.bounds;
CGRect rightRect = CGRectOffset(normalRect, normalRect.size.width, 0);
CGRect leftRect = CGRectOffset(normalRect, -normalRect.size.width, 0);
mainTabBarController.view.frame = leftRect;
detailedNavigationController.view.frame = normalRect;
[self.window addSubview:mainTabBarController.view];
[self.window addSubview:detailedNavigationController.view];
[UIView animateWithDuration:0.35 delay:0.0 options:UIViewAnimationCurveEaseOut
animations: ^{
mainTabBarController.view.frame = normalRect;
detailedNavigationController.view.frame = rightRect;
}
completion: ^(BOOL finished){
[detailedNavigationController.view removeFromSuperview];
}];
}
I think this solution is better then emulating of tab bar, since it doesn't break UIViewContoller's life cycle.

Related

How to use presentModalViewController in iPad

I have created a Cartview and want to display this view as a modalview when i click a button on productview.How can i do this ?
Actually i did this like
UIViewController *nav=[[UIViewController alloc]initWithNibName:#"CartView-iPad" bundle:nil];
nav.modalPresentationStyle=UIModalPresentationFormSheet;
nav.modalTransitionStyle=UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:nav animated:YES];
CGRect frame=nav.view.frame;
frame.origin.x -= 75;
frame.origin.y = 100;
nav.view.frame=CGRectMake(frame.origin.x, frame.origin.y , 672, 393);
But the problem is the formsheet view is coming and my cart view is coming overt that i need only my cartview.Also i need a close button on the right to side of the cartview to dissmiss the modalview.
The problem may be that you're trying to set the frame of the modal view controller manually. This is, as far as I know, not recommended. The UIModalPresentationFormSheet option already indicates the desired size of the modal.
As for a back button, you should add a navigation bar with a back button in your CartView-iPad-xib-file. To make it work you have to make a subclass of UIViewController (example: CartViewController) which will handle the back button press. Right now nav is just a normal UIViewController which has no idea what to do with the actions in your xib-file.
Then in your new view controller, you can make a function like this that you connect your back button to:
- (IBAction)backButtonPressed
{
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}

Switch/Navigate between Tabs in TabBarController

So I have 2 tabs in my tab bar controller.
I have a button in Tab 2, and if I click that, control needs to be passed to Tab 1, and it should become the present view controller.
//I should not use navigation for this because the view would navigate
the present view to the view in tab 1 ; but the tab will still indicate Tab 2//
I just need it to go to tab 1 when I click the button.
When you click the button, just have it send the following
self.tabBarController.selectedIndex = 0;
That will tell it to switch to the first tab in its index (Tab 1)
If you want to add animation to the change, you'll use transitionFromView:toView:duration:options:completion:. And to implement this, you'll use something like this:
[UIView transitionFromView:self.view
toView:[[self.tabBarController.viewControllers objectAtIndex:0] view]
duration:1 /*or whatever time you want*/
options:/*specify your animation transition here, they are found in the UIView documentation*/
completion:(void (^)(BOOL finished))completion:^(BOOL finished) {
if (finished) {
tabBarController.selectedIndex = 0;
}
}];
The options give you control how it transitions, and there's a nice list of all the stuff you can do. Then the completion block lets you specify what to do once you're finished. In this case, it will switch to tab 1 so it is the new primary controller
You can set your UITabBarController's selectedIndex or selectedViewController property to programmatically change the current tab.
Would you be able to set the selectedIndex property on your UITabBarController?

Tab Bar controller is not accessible

I have created a tab based application for iphone. when the 1st tab presses a first view will present. this view contains a button, on pressing it another view loads.
Code is:
-(IBAction)buttonPressed: (id) sender
{
Cities *cv=[[Cities alloc] initWithNibName:#"Cities" bundle:nil];
cv.modalTransitionStyle=UIModalTransitionStyleCoverVertical;
[self presentModalViewController:cv animated:YES];
[cv release];
}
Now problem is that this view is loading in whole screen so that I am not able to access tab bar.
I have set the frame for this view and the view is loading in this frame,
-(void)viewWillAppear:(BOOL)animated
{
self.view.frame = CGRectMake(0, 0, self.view.frame.size.width, 400);
}
but in remaining part white screen is appearing means tab bar is not accessible.
I want that whatever will be load at any time tab bar should be always accessible.
Please help me out.
Add
cv.modalPresentationStyle = UIModalPresentationCurrentContext;
Have you tried using UINavigationController inside your tabbar to dig inside your UIViewControllers??
for Ref : Adding NavigationController to Tabbar
do you really need a viewController Class for what you are trying to display??
if der's no core functionality being used, i think it will be much easier with UIView.
Happy Coding :)

iPhone's UITabBar as part of application window; problems when rotating device

I have an iPhone application that's using Navigation Controller to display the top bar (with title and back button, and such...).
I added a UITabBar to the application window, that enables to switch between the parts of it. Instead of adding the tab bar to each of ViewController's view I added the bar to app window.
(When I had it in the ViewController, switching between controllers made the tab bar to swipe left/right, when animated pop/push occured, together with whole view).
So, I added the UITabBar to the MainWindow.xib, and tied it to the app delegate's variable. In my didFinishLaunchingWithOptions method, I added the following code:
[self.window addSubview:navigationController.view];
CGRect frame = navigationController.view.frame;
frame.size.height -= tabbar.frame.size.height;
navigationController.view.frame = frame;
tabbar.selectedItem = [tabbar.items objectAtIndex:0];
to resize the main (navigationController's) view, in order to make the TabBar visible.
The problem shows up when I rotate the device -- my view gets stretched to full window and I loose the ability to show the TabBar.
I added a - (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation) fromInterfaceOrientation method to my ViewController, with the following code:
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
CGRect frame = self.view.frame;
frame.size.height -= [AppState shared].tabBar.frame.size.height;
//frame.origin.y = [AppState shared].tabBar.frame.size.height;
//frame.origin.x = 100;
self.view.frame = frame;
frame = [AppState shared].tabBar.frame;
frame.origin.y = [UIScreen mainScreen].bounds.size.height - frame.origin.y - frame.size.height;
[AppState shared].tabBar.frame = frame;
}
It resizes the view, and moves the tab bar to up/down part of the view (I allow only Portrait/Portrait upside down orientations here). The problem is, my TabBar is turned upside down as well, and also, it's no longer clickable.
It looks like the image below:
Anyone knows how to handle this kind of situation? Or, how to make the tab bar not tied to view controller, but also able to handle interface's rotation smoothly?
You are using the tabbar in an unintended way. You seem to be using the UITabBarView as an uncontrolled element of other views. That is not it's function.
The UITabBarView should be controlled directly by a UITabBarController which in turn should be controlling all the view controllers for the views displayed in the tabbar i.e. the tabbar controller is a type of navigation controller that controls subcontrollers.
Suppose you have three tabs and the third one is a navigation controller. Your controller hierarchy would look like this:
TabbarController:
-->tab1ViewController
-->tab2ViewController
-->tab3ViewController(UINavigationController):
-->rootViewController-->secondViewController
You are trying to move and manage the tabbar view without its controller and the proper controller hierarchy. That isn't going to work.

Showing/hiding navigation bar with smooth animation

I have a navigation based app. The first view (rootcontroller) starts with three large buttons only. No navigationbar. From there, everything else is tableviews and have navigation bars. I'm doing this to show/hide the navigation bar:
MyAppAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.navigationController.navigationBar.hidden = NO;
Once I leave the root controller, the navigation bar will jerk into place and lay on top of the tableview, rather than pushing it down. It clips the top part of the tableview. Going back to the root controller isn't smooth in how the navigation bar disappears. Is there a smoother/better way to do accomplish hiding the navigation bar for the root controller only?
You can use [navigationController setNavigationBarHidden:YES animated:YES] to hide the bar smoothly.
Reference
This nifty bit of code animates the navigation bar hiding with no UI issues:
[navigationController setNavigationBarHidden: YES animated:YES]
But...
Use the self.navigationController.navigationBarHidden property for checks in the code instead of the self.navigationController.navigationBar.hidden property. This will save you a lot of pain from unexpected UI positioning problems.
Take care to place this method in - (void)viewWillAppear:(BOOL)animated or later in the view lifecycle. This is recommended because if you do it in - (void)viewDidLoad for instance, you will get an ugly black rectangular view during animations from a view which displays its navigation bar to a view which doesn't!
For example, if your home view has its navigation bar hidden but all its children have the navigation bar shown, when you pop to home view, the animation will show a black bar in place of the navigation bar until the animation completes
You can customize the navigation bar animation and duration by the following methods. It will provide you callback once animation will be completed.
// pass a param to describe the state change, an animated flag and a completion block matching UIView animations completion
- (void)setNavigationBarVisible:(BOOL)visible animated:(BOOL)animated completion:(void (^)(BOOL))completion {
// fail if the current state matches the desired state
if ([self navigationBarIsVisible] == visible) return completion(YES);
// get a frame calculation ready
CGFloat nheight = self.navigationController.navigationBar.frame.size.height;
CGFloat noffsetY = (visible)? -nheight : nheight;
// zero duration means no animation
CGFloat duration = (animated)? 0.3 : 0.0;
[UIView animateWithDuration:duration animations:^{
CGRect nframe = self.navigationController.navigationBar.frame;
self.navigationController.navigationBar.frame = CGRectOffset(nframe, 0, noffsetY);
} completion:completion];
}
// know the current state of the navigation bar
- (BOOL)navigationBarIsVisible {
return self.navigationController.navigationBar.frame.origin.y < CGRectGetMinY(self.view.frame);
}
// Show or Hide navigation bar
[self setNavigationBarVisible:![self navigationBarIsVisible] animated:YES completion:^(BOOL finished) {
NSLog(#"navigation bar finished");
}];
Before hide a Navigation bar:
After hide a Navigation bar: