Keep a header view when using a navigation controller - ios

I have a label I placed at the top of the screen as a header. I want to keep that viewable and still present when I add a navigation controller by embedding it.
I am mostly using the storyboard to help me create the UI.
This is what the app looks like without a navigation controller:
However, if I add a navigation controller I get the following:
Certainly I would like to maintain a navigation controller so that I won't have to incorporate my own buttons which control navigation. As I understand it, at this time the Marketplace logo is hidden behind the nav controller.

You can use two methods here :
1) Keep using your label, and hide the navigation bar , your app will still have navigation, just the top navigation bar will be hidden.
For this, use this code:
viewDidLoad()
{
self.navigationController?.navigationBar.isHidden = true
}
2) The second method is a alternate to what you want, but its good if you Need text At top only. In this we will not use label, instead we'll set title of the navigation bar itself.
viewDidLoad()
{
self.navigationItem.title = "MarketPlace"
}
Maybe there are more methods, but these two i've used.

You can try navigationItem.titleView = yourView

In Objective-C it would be something like this:
navigationController.navigationBar.hidden = YES;

Related

Custom NavigationBar height with button and label

I'm trying to create a UINavigationBar that looks like this:
This is what I've managed to achieve...
My first idea was to try creating a back button on the UINavigationBar and just removing the line between the first header of the UITableView. Problem with that is, the UITableView header is not sticky. Can someone help me out with this?
I'm using Swift 4
My solution was this: Create a new UIViewController and put a View at the top of it as my header then use a UITableView as opposed to a UITableViewController.
You should be able to achieve that with the prefersLargeTitles setting on UINavigationBar available from iOS 11. If you're using a Storyboard, select the navigation bar, and check the "Prefers Large Titles" box.
In code, you can set the navigation bar's prefersLargeTitles property to true.
When you show a detail view controller, you may want to have more control over whether it uses the large title or not. You can do this on the view controller.
Easiest way to do that is in code. Something like this:
override func viewDidLoad() {
super.viewDidLoad()
// Disable large titles for this view controller
navigationItem.largeTitleDisplayMode = .never // Options are automatic, always, or never.
}

Custom navigation back button with custom title in swift3

I need to implement the navigation bar with custom back image and custom title. For example: if i am in "Login with facebook" page i need to show the "Login with facebook" besides the custom back image. For this i am following the code like this:
let yourBackImage = UIImage(named: "back_button_image")
self.navigationController?.navigationBar.backIndicatorImage = yourBackImage
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = yourBackImage
self.navigationController?.navigationBar.backItem?.title = "Custom"
But I am getting the output like this:
Note: The title is of the current page.
How to achieve this?
If the back title is too long iOS will change it to 'Back'.
However if you add a left bar button item - this you can set to a longer length.
long back
From Apple docs: https://developer.apple.com/documentation/uikit/uinavigationcontroller
In cases where the title of a back button is too long to fit in the available space, the navigation bar may substitute the string “Back” for the actual button title. The navigation bar does this only if the back button is provided by the previous view controller. If the new top-level view controller has a custom left bar button item—an object in the
leftBarButtonItem
or
leftBarButtonItems
property of its navigation item—the navigation bar does not change the button title.
To do this go to the Storyboard, in Interface Builder, drag a Bar Button Item into your navigation bar and set its title.
*Note that you will need to hook this up to your view controller to pop it.
#IBAction func pop(_ sender: UIBarButtonItem) {
_ = navigationController?.popViewController(animated: true)
}
You'll find a lot of StackOverflow attempts to answer this (quite common) issue, and the best way that I've found is also rather complicated. You'll have to do this for every UINavigationController, UINavigationBar, and UINavigationItem in your app, and that's painful.
How Apple wants you to do it (as far as I can tell)
For UINavigationBars in a storyboard, set the Back and Back Mask values (in the Attributes inspector) to the name of your custom image.
For every view controller's UINavigationItem, set its Back attribute value to an empty string or single space.
Easy enough, right? Nope. For one thing, the empty string or single-space Back title isn't always honored. And what if you have dozens, or even hundreds, of view controllers? What if your application has multiple UINavigationControllers? What if you set configure your view controllers (or at least their navigation items) programmatically? Then it's not so easy.
How StackOverflow thinks you should do it
I'm not going to link to all of the SO answers that recommend this way of doing things. I'll just summarize it as:
Hide the navigation item's back button with UINavigationItem.setHidesBackBarItem(_:animated:).
Create a UIBarButtonItem with your custom back image and empty title, then add it to your navigation item's leftBarButtonItem.
Sit back and wait for user bug reports to flood in with complaints that your app doesn't support swiping to navigate back.
Or, if you want to be clever, attach your navigation controller's interactivePopGestureRecognizer to your custom left bar button item. This usually works, but it feels like a hack that's likely to break in future releases. If you're ok with that, then you can stop reading right here.
How I think you should do it
If you have a lot of view controllers (our app has 200+) and/or a mix of VCs configured programmatically and in storyboards, this may ultimately be an easier way.
Create a subclass of UINavigationBar and set this as the class for all navigation bars in your storyboards and code. (If you're doing it in code, note that the nav bar is a read-only property; it can be set only in the navigation controller's initializer.)
The UINavigationBar manages a stack of UINavigationItems, one for each view controller on the UINavigationController's stack, and keeps them in sync with their view controllers. In other words, when you push a view controller onto the nav controller, that view controller's nav item also gets pushed onto the nav bar, and it gets popped when the VC is popped. When the navigation bar pushes or pops an item, it uses the new topmost item's title, titleView, and/or button item properties to set configure its own title view and buttons, and uses the title of the navigation item immediately below the topmost one to configure its back button and back image. If the next-to-topmost item's title is nil, then the nav bar uses the default value of "Back". You don't want that. If you can set the Back attribute to an empty or single-space string in the storyboard, then you should be able to do the same thing in code, right? Wrong. The back text is not a public property in UINavigationItem! WTF?
Instead, you have to set the title of the next-to-topmost item to an empty string. "But wait!" you say, "Doesn't that permanently change the next-to-topmost item's title, so that when I navigate back to that view controller, its title will say "Back" instead of its original title?" And you'd be right. What can you do? In your subclass of UINavigationBar, add an array of Optional title strings, like so:
var navigationItemTitles = [String?]()
(Why Optional? Because navigation items may have a custom titleView instead of a title.)
Override the navigation bar's pushNavigationItem(_:animated:) and popNavigationItemAnimated(_:) so that they modify and restore the navigation items' titles, respectively:
override func pushNavigationItem(_ item: UINavigationItem, animated: Bool) {
super.pushNavigationItem(item, animated: animated)
// Store the new back item's title, then set its title to
// an empty string.
if let backItem = backItem {
navigationItemTitles.push(backItem.title)
backItem.title = ""
}
}
override func popNavigationItemAnimated(_ animated: Bool) {
super.popNavigationItemAnimated(animated)
// Restore the new top item's title.
if navigationItemTitles.count > 0 {
topItem?.title = navigationItemTitles.popLast
}
}
Caveats
This is the only way I've found that's foolproof and not hacky. If Apple simply made the navigation item's Back property publicly settable, then a lot of this could be avoided.
(For what its worth, not only does our app have 200+ view controllers, it also has multiple navigation controllers with different navigation bar looks and feels. That's a whole other layer of complexity.)

Swift - How to set a different nav bar for each view?

enter image description hereI'm having trouble displaying different navigation bar button on different views.
I have a parent view navigation controller and 3 child views. What I would like to do is have different navigation bar buttons on each child view, and not just the same 2 which I could achieve through adding them on the main storyboard.
I have attached two screenshots so you can see what my storyboard and code looks like.
So basically I'm looking for some code to add bar items individually on each view.
[![enter image description here][2]][2]
In each view controller you can use self.navigationItem to make those changes individually.
For example, say you have a view controller names "VC1" and you want to have an add button in the navigation bar. In VC1, override viewDidLoad and do the following:
override func viewDidLoad() {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "addFunc")
}
UPDATE:
So, looking at your tutorial I realized that you're not pushing the child view controllers to the navigation controller, you're just adding them as child. There is a difference. Every navigation controller has a set of view controllers (you can access this: navController.viewControllers)
You can add child view controllers but it would not be any different from other controllers, if you want to actually use a navigation controller, you need to push them to the navigation controller. Otherwise, you can't access navigationItem or similar features like that.
Instead of adding the view controllers to the scroll view, use this:
self.pushViewController(childViewController1, animated: true)
If you absolutely want to have it in the scroll view AND have different navigation bar buttons for every view controller, you'd have to implement this mechanism yourself. For example, check out this:
https://github.com/peymanmortazavi/UISwipeViewController
It's not polished, you'd have to implement the layout constraints properly but it demonstrates what I mean.

Questions about navigation bar

I am confused about the relationship of navigation controller and content view controllers. In storyboard, navigation bar is under the navigation controller, so I linked it to the NavigationController class and then customized the navigation bar in the viewDidLoad function. However, since different content views will have different navigation bar, like different bar buttons, how can I realize this? Just some basic ideas are good enough. My guess is that I need to specify specific bar buttons in specific content view controllers, but since the navigationBar property is in NavigationController class, how can I refer to it?
I want to hide the title of the navigation bar and make the bar only show some custom buttons (I know toolbar may match it better, but I have other reasons to adopt navigation bar). Please tell me how to hide the title in detail and swift language is preferred.
1) Every ViewController instance has a navigationController property, it' just an optional. To set the bar buttons, you'll want to use navigationItem. So to specify bar buttons you either do so in Interface builder per view controller, or just or do something like this in viewDidLoad
let navBarButton = UIBarButtonItem()...set up bar button
self.navigationItem?.leftBarButtonItem = navBarButton
2) Hiding the title is trivial:
self.navigationItem?.title = ""

Using splitviewcontroller with storyboards?

I have created a splitview controller in a storyboard that has a navigation bar across the top. I also have a master view with a tableview that when selected displays the correct view in the detail view controller.
How can I update the splitview controller's navigation bar title? I know I can access the master's nav bar through "self.navigationItem.rightBarButtonItem" but how do I access the main nav bar from this file?
Thanks
If you have a navigation bar across the top, then you can set the title like this:
self.title = #"this is my title";
If your title is fixed and doesn't change, then just add that line in your viewDidLoad method or where ever you would setup items in your view.
If you are trying to set the title programmatically, then it depends on which view controller you are in when you try to set the title. In the example above, it will set it for the view controller you are in.
If you want to set the opposite view controller navigation bar, you have a couple of ways to choose from depending on when you want to update it.
Generally though you would reference the opposite view controller directly using a delegate or indirectly using the splitViewController.viewControllers array.
it sounds like you already have a reference to the detail view controller. If so and you want to change its title from the master you can do so like this:
[self.detailViewController setTitle:#"New Title"];
hope that helps,
be well

Resources