ios7 presentViewController reverts navBar from new 64px bar back to old 44px version - objective-c

I have an application that is supporting only ios7+ The navbar setup is using the new 64px high bar that appears beneath the status bar. Here is what it looks like when the app launches:
If I do any sort of "presentViewController", when i dismiss the view the navbar shifts back to 44px height and still appears underneath the status bar which in-turn makes all the contents of the view also shift up. Here is what that looks like:
It doesn't matter if I am presenting one of my own views or if I simply present a UIImagePickerView, any sort of slide up modal via the navigation controller breaks the navbar setup. Any ideas on how to fix this?
A few notes:
in plist: "View controller-based status bar appearance" is set to "NO"
navbar configured with self.navController.navigationBar.translucent = NO;
I am using .xib NOT Storyboards
UPDATE:
I have the navigation controller inside of a PKRevealController (https://github.com/pkluz/PKRevealController). Taking the reveal controller out and just adding the nav controller to the window itself fixes the issue... why would the reveal controller cause it to behave differently?
SOLUTION:
It turned out that the PKRevealController library was causing the issue. I reworked how it was set up in the AppDelegate and that solved the problem, although it's sorta of "hacky". I put my "before" and "after" configurations below:
the initial setup was :
configure PKRevealController
configure NavController and add rootView
set pkreveal front view = navController
add reveal controller to window as windows root view
the fix is
create a containing NavController
do stpes 1-3 above
add pkrevealcontroller to the containing navController
set containing nav controller nav bar to hidden
add containing nav controller to window as root view

If its navigationcontroller than you can use this inside every viewcontroller's viewdidload:
if ([self respondsToSelector:#selector(edgesForExtendedLayout)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}

I had the same problem, but solved very easily by just setting the UINavigationBar Y-position to 20px and not to 0px. Then you have to assign the UINavigationBarDelegate to your ViewController:
[_navigationBar setDelegate:self];
Furthermore you have to add this method to your ViewController, which will be called because of the Delegate assignment:
-(UIBarPosition)positionForBar:(id<UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}

Related

iOS - Set UIToolBarItem on UINavigationController

I drag out a toolbaritem in storyboard and set it on my nav controller, but when I run my code it's not there, is there something I'm missing?
EDIT:
Tried setting it in code as well in my viewDidLoad method:
UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithTitle:#"Map" style:UIBarButtonItemStyleBordered target:self action:#selector(viewMap)];
self.navigationItem.rightBarButtonItem = rightBarButton;
Won't work either.
Here's how it's set up in my storyboard:
UPDATE:
Just found my problem. In my controller code when I update it's contents I change the right bar button item for a spinner and never set it back to what it had before.
UINavigationController already has a toolbar built in. It has a property toolBarHidden which is set to YES by default, which is why it is not normally seen. If you are using storyboard you can easily make the built-in bottom toolbar visible by checking the checkbox "Shows Toolbar" in the inspector when the Navigation Controller is selected.
See the UINavigationController documentation here for more details.
EDIT:
Ok, it sounds like what you are trying to do is add a right button to your view controller's UINavigationItem. To do this in storyboard, drag a "Bar Button Item" from the Objects Library onto the Navigation Item in your ViewController. You can then set the title/style/etc of the bar button item. If nothing still shows up when you run your app, make sure that your ViewController is connected properly with a segue to the navigation controller.
Also make sure you are adding the Bar Button Item to your view controller's Navigation Item, NOT to the View Controller itself. Here is how the setup should look in your storyboard:
To add an item to a navigation bar, you need to add a Bar Button Item to the Navigation Item contained in the view controller. Go to your storyboard, find the right VC, and find the navigation item (it's in the hierarchy shown in the navigation controller 'scene'). Just drag a Bar Button Item into that hierarchy underneath the nav item, or directly onto the navbar in the visual builder display.
The navigation controller only looks at your VC's nav item when that VC is pushed onto the stack; hence modifying the VC's nav item in viewDidLoad has no effect.
(I've done this programmatically before but I don't have the code with me, so maybe I'll add that later...)

Top Bar does not appear for presentModalViewController

I've created a UIViewController subclass called addItemToListViewController. I selected add an "xib" as well, and just created a simple page with a couple of labels and a textField. In the interface builder I selected "Top Bar - Navigation Bar" so that when it is put on the stack when the application runs it will have a top bar that will match the initial main window. In the Interface builder it shows the top border, but when I run the application in the simulator the top bar is not present once the view is displayed.
Here is the code I placed in the rootViewController to present the view controller
- (IBAction)addButtonPressed:(id)sender
{
AddItemToListViewController *addItemToListViewController = [[AddItemToListViewController alloc] initWithNibName: #"AddItemToListViewController" bundle:nil];
[self presentModalViewController: AddItemToListViewController animated: YES];
[AddItemToListViewController release];
}
I'm only able to have the top bar present if I manually add a Navigation bar to the xib. If I must add a Navigation bar to my xib, what is the purpose of the "Top Bar" attribute?
- (IBAction)addButtonPressed:(id)sender
{
AddItemToListViewController *addItemToListViewController = [[AddItemToListViewController alloc] initWithNibName: #"AddItemToListViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addItemToListViewController];
[self presentModalViewController: navController animated: YES];
[AddItemToListViewController release];
[navController release];
}
That "top bar - Navigation bar" in InterfaceBuilder is what's known as a "Simulated Metric". It's there to help you lay out your view with correct spacing when other visual elements - the status bar, navigation bar, or tab bar - might consume some of the device's screen real estate. It doesn't actually do anything other than shrink the vertical dimensions of the view defined by the NIB. The purpose is to help you layout your view, not to actually create a component that will appear in your app.
If you want a navigation bar, then you have two choices. The first choice is to use a navigation controller (of which your initial view will have to be the root) and call
[self.navigationController pushViewController:newVC animated:YES];
The process of setting up a navigation controller correctly, etc, is nontrivial, and you should do some searching to find the best way to do that for your app. For a simple app, especially if you're just learning iOS, you can use the "Navigation-based Application" template when you create a new project. With a navcon, you get all the fancy behavior normally associated with that top bar - an automatic back button, fancy left/right scrolling when you transition to a detail view, etc.
The second option is to put a "fake" navigation bar in the detail view, using the Navigation Bar object. You can find that object, plus some other related objects, in the bottom half of the "Utilities View" (the right-most pane) in XCode. Just drag the object into your XIB and blammo, you have a 44-pixel tall gray bar. This navigation bar is just like what you get when you use a Navigation Controller except you don't get the stack functionality; you can still add buttons to the left and right, change the title, tint it to a specific color, etc.
The xib does not know you will use the controller as a modal view as it could also be used for a normal view which could show a top bar. Only when you push the view it will use or ignore the showing of this top bar.
In short: its there in case you will use the xib for a normal view :)

Xcode Adding Subview on entire screen above everything

I want to use addSubview method to add new view on my screen. However, new view must also include navigation bar etc. which means it should include entire screen. What should i do?
Whenever i try to addSubview it always shows new view under navigation bar.
I don't want to use pushViewController or presentModelViewController because new added view will be low opacity and i can see background but i do not want to interact with background objects like bar buttons table etc.
Sorry for english, i hope, i clearly told what problem is.
Just set the frame property of the view you add before, and set it with screen bounds.
[myView setFrame:[[UIScreen mainScreen] bounds];
[self.navigationController.view addSubview:myView];
If you want to disable interaction with the navigation bar :
[self.navigationController.navigationBar setUserInteractionEnabled:NO];
You could take a look at adding another UIWindow above your root window.
when I tried doing the navigationController.view addSubview, it wouldn't cover my tab bar so I did the following with my app delegate's window:
[self.window addSubview:myView];
if you need access to your appDelegate from another class, you'd just import your application delegate and call it from that.

Adding a Navigation Controller to a View based Application adds top margin

I am trying to programmatically add a Navigation Controller to my View based Application. This is the code I am using (this code gets called after a button press in a view controller):
MainMenu *control = [[MainMenu alloc] initWithNibName: #"MainMenu" bundle: nil];
UINavigationController *navControl = [[UINavigationController alloc] initWithRootViewController: control];
[self.view addSubview:navControl.view];
[control release];
That works, but this ends up happening:
Notice the odd margin above the Navigation control.... My View controller that I am adding the Navigation Controller to has a gray background which you can see.
Any ideas??
If you have a better way of adding a Navigation Controller to a View based Application I am very open to suggestions!
Thank you in advance!
Thank you both for your response, but unfortunately, wantsFullScreenLayout set to YES or NO in the code didn't have any effect. I was able to push the Navigation Controller up by 20 using this line of code:
self.navigationController.navigationBar.frame = CGRectOffset(self.navigationController.navigationBar.frame, 0.0, -20.0);
but then what happened was that the View Controller did not move up with the Navigation bar and left a gap below the Navigation Bar and the View Controller. What eventually worked was checking the Wants Full Screen checkbox in IB in the MainWindow view controller that is automatically generated when you set up a view based application.
The gap you are seeing is the same height as a status bar. Check the status bar settings in your NIB file.
Chances are you want to make the UINavigationController the root view controller for the window, rather than whichever view controller you have now. That would be the better way to do it.
The reason you're seeing that extra margin at the top is because UINavigationController normally expects that it will be sized to fill the entire screen (except perhaps a tab bar at the bottom, if it's inside a UITabBarController), and therefore expects that the top edge of its view will be under the status bar if the status bar is visible. Therefore, it places its navigation bar 20 pixels below the top of its view to leave space for the status bar, without bothering to check whether its view actually is under the status bar. Interestingly, sometimes a re-layout operation will perform this check, but that's unreliable. What I've found works well in a situation like this is to set the UINavigationController's wantsFullScreenLayout property to NO. Then ti doesn't try to leave room for the status bar, so everything works as expected.
I've been struggling with this same issue this morning. Since setting the wantsFullScreenLayout property doesn't seem to have any effect, I resorted to using a little subclass, which worked fine:
#interface MyNavigationController : UINavigationController
#end
#implementation MyNavigationController
- (BOOL)wantsFullScreenLayout;
{
return NO;
}
#end
Its so simple to remove that gap..
self.navigationBar.view.frame = CGRectMake(0, -20, 320, 480);

UINavigationController without NavigationBar

I have a "landing page/view" that I dont want the navigation bar to show, so I turn it off during the viewDidAppear
navigationBarHidden = YES;
When i push a view on the stack and then move it off. the main landing page shows the nav bar then hides it which cause a flicker that I dont want.
is there a way to have the landing page be a UIView or something? When a menu item is touched the app would push a new view on top of the default landing page. It sound like it would be hard to do without having the landing page be a UINavigationController. Any thoguhts?
Try hiding the navigation bar in viewWillAppear, rather than viewDidAppear.
If you don't need to go back to the landing page, use a view controller for the landing page and present it modally from the navigation controller when the application starts.
So you do want to go back to the landing page.
It's hard to accomplish that with UINavigationController. Suppose your are going back to the landing view. While the transition, the old view should have a navigation bar, and the new view (landing page) should not have a navigation bar. UINavigationController does not allow you manually modifying the transition animation. In other words, you cannot animate hiding/unhiding the navigation bar along with push/pop animation (using viewWillAppear doesn't solve the problem).
So what would I do, if I really, really need this?
I would have a rootViewController (of UIViewController), whose view is the only subview of your application window. When your application starts, rootViewController add the landing view as a subview of its view. When the user selects an item there, you create an UINavigationController with the corresponding view controller as its root view controller.
And, using CATransition animation with type of kCATransitionPush and subtype of kCATransitionFromRight, you add the view of the navigation controller as a subview of rootViewController's view.
Then you need a 'back' button for the first view of the navigation controller. In all view controllers that are the first level view controllers of the navigation controller, create a bar button item with a text 'Back', and add it to their navigationItem.leftBarButton property. Set a target-action (probably to the rootViewController) pair for the button.
When the action message fires, use CATransition animation (now with kCATransitionFromLeft subtype), to remove the current navigation controller's view from rootViewController's view.
The transition may not look as perfect as the native UINavigationController, but I believe this is the best you could get.
Actually the way to do this is to implement UINavigationController's delegate method navigationController:willShowViewController:animated. This method is where you should handle hiding and showing your navigation bar so the animation will occur during the push/pop animation.
I came across a method that is simple and works well for me, and is not given here yet. I assume you have a view controller for the main landing page and it is set as root view controller of the navigation controller. Then you should hide/show the navigation bar in the viewWillAppear and viewWillDisappear methods of the main landing page controller:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
Source:
http://www.iosdevnotes.com/2011/03/uinavigationcontroller-tutorial/