How to add title/button to a UINavigationController added inside a UIViewController? - ios

For some reason, I have to add a UINavagationController() inside a UIViewController(), so I did the following in the view controller class:
class someViewController: UIViewController {
private let myNav = UINavigationController()
override func viewDidLoad() {
self.addChildViewController(myNav)
self.view.addSubview(myNav.view)
myNav.view.translatesAutoresizingMaskIntoConstraints = false
myNav.view.topAnchor.constraintEqualToAnchor(self.topLayoutGuide.bottomAnchor).active = true
myNav.view.leftAnchor.constraintEqualToAnchor(view.leftAnchor).active = true
myNav.view.rightAnchor.constraintEqualToAnchor(view.rightAnchor).active = true
myNav.view.heightAnchor.constraintEqualToAnchor(nil, constant: 44).active = true
myNav.didMoveToParentViewController(self)
}
}
The navigation controller is added & showing up correctly. Then I try to add a title (or Done button) to the navigation bar, however the items just don't show up. I tried a few things like this:
self.navigationItem.title = "some title"
myNav.navigationItem.title = "some title"
myNav.navigationItem.rightBarButtonItem = btnDone
What's the right way to do it in this case?

Why don't you use this simple code to add a navigation bar :
let navigationBar = UINavigationBar(frame: CGRectMake(0, 0, self.view.frame.size.width, 66)) // Offset by 20 pixels vertically to take the status bar into account
// Create a navigation item with a title
let navigationItem = UINavigationItem()
navigationItem.title = "Title"
// Create left and right button for navigation item
let leftButton = UIBarButtonItem(title: "Save", style: UIBarButtonItemStyle.Plain, target: self, action: "btn_clicked:")
let rightButton = UIBarButtonItem(title: "Right", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
// Create two buttons for the navigation item
navigationItem.leftBarButtonItem = leftButton
navigationItem.rightBarButtonItem = rightButton
// Assign the navigation item to the navigation bar
navigationBar.items = [navigationItem]
// Make the navigation bar a subview of the current view controller
self.view.addSubview(navigationBar)

Related

Why does setting a custom backBarButtonItem for a UINavigationItem result in double back buttons?

I have a very simple setup. A UINavigationController with a root UIViewController that modifies its navigation item with a custom back button item on viewDidLoad.
let backButton = UIBarButtonItem(image: backArrowImage,
style: .plain,
target: nil,
action: nil)
navigationItem.backBarButtonItem = backButton
I'm expecting this to completely replace the system back button with title and the default back arrow icon.
However when I push a new view controller on the stack, the navigation bar draws both the new custom back icon and the system back icon.
This is what I'm seeing:
This is what I would expect it to look like:
You can hide the back button
navigationItem.hidesBackButton = true
and use leftBarButtonItem for custom UIBarButtonItem
UPD
import UIKit
final class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.hidesBackButton = true
let backItem = UIBarButtonItem(image: backArrowImage, style: .plain, target: self, action: #selector(backButtonPressed))
navigationItem.leftBarButtonItem = backItem
}
#objc func backButtonPressed() {
navigationController?.popViewController(animated: true)
}
}
let backBarButtonItem: UIBarButtonItem = .init(
image: UIImage(systemName: "chevron.backward"),
style: .plain,
target: target,
action: action
)
navigationBar.topItem?.backBarButtonItem = backBarButtonItem
navigationBar.backIndicatorImage = UIImage()
navigationBar.backIndicatorTransitionMaskImage = UIImage()
This works for me, to setup custom "<" and hide the default one and still keep the backBarButtonItem behaviours
The solution was to set global UINavigationBar appearance.
Apparently this has to be done at app launch.
UINavigationBar.appearance().backIndicatorImage = backArrowImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backArrowImage
With this approach we can preserve title animations and general back button behavior that would not be preserved if supplementing the back button with the leftBarButtonItem.

How to change UINavigationController Title & backButton programming?

I have two viewControllers.
vc1 -> presentVC -> vc2
vc2 inherit UINavigationController
I want to set title & backButton in vc2,but it doesn't work.
class vc2: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
// set title!!!
//self.navigationItem.title = "123"
//self.navigationController?.navigationBar.topItem?.title = "123"
//self.title = "123"
//self.navigationBar.topItem?.title = "123"
//self.navigationItem.title = "123"
// set backButton!!!
let navButtonWidth:CGFloat = 44
let backButton:UIButton = UIButton()
backButton.setImage(backImage, for: .normal)
backButton.addTarget(self, action: #selector(back), for: .touchUpInside)
self.navigationItem.leftBarButtonItems = [UIBarButtonItem(customView: backButton)]
}
Place the code below in perform(segue) or viewWillDissappear depended on how do you do your presentation - via Storyboard segue or manually from code.
let backButton = UIBarButtonItem()
backButton.title = "whatever_you_want"
navigationItem.backBarButtonItem = backButton
And in viewDidLoad of your vc2 simply put
navigationItem.title = "Controller title"
I can change it in storyboard Or change it in code.
I usually do this.
First hide navigation bar from default navigation controller.
navigationController?.navigationBar.hidden = true
Create navigation bar in storyboard and outlet it.
#IBOutlet weak var navigationBar: UINavigationBar!
Create custom navigation item.
private lazy var customNavigationItem: UINavigationItem = {
let navigationItem = UINavigationItem()
let backButton = UIBarButtonItem(image: UIImage(named: "cancel_icon"), style: .Plain, target: self, action: #selector(cancelTapped))
navigationItem.leftBarButtonItem = backButton
navigationItem.title = "Your Title"
return navigationItem
}()
Add custom navigation item to navigation bar
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.hidden = true
navigationBar.setItems([customNavigationItem], animated: false)
}
Hope it help.

Create navigation item with default Icon programatically IOS

I want to create a navigation item "Refresh" with the default XCode refresh Icon programmatically. I know how to create one with the word "Refresh" with the following code. However, I want to have the icon insetead of the word "Refresh" Thanks for helping in advance
let refreshButton = UIBarButtonItem(title: "Refresh", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(FollowVC.refresh))
Superb question.I tried sample one for your question.I got the solution and It works fine.
what you made mistake in your coding is
First your
let refreshButton = UIBarButtonItem(title: "Refresh", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(FollowVC.refresh))
is wrong.You have to use or write
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem, target: AnyObject?, action:Selector)
Second you used UIBarButtonItemStyle.Plain.If you want refresh button you have to set UIBarButtonSystemItem.Refresh.
SWIFT
override func viewDidLoad()
{
// Create the navigation bar
let navigationBar = UINavigationBar(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: self.view.frame.size.width, height: 64))) // set frame here
//set the background color
navigationBar.backgroundColor = UIColor.white
navigationBar.delegate = self as? UINavigationBarDelegate;
// Create a navigation item with a title
let navigationItem = UINavigationItem()
navigationItem.title = "title" //If you want to set a tilte set here.Whatever you want set here.
// Create button for navigation item with refresh
let refreshButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.refresh, target: self, action: Selector(("actionRefresh:")))
// I set refreshButton for the navigation item
navigationItem.leftBarButtonItem = refreshButton
// Assign the navigation item to the navigation bar
navigationBar.items = [navigationItem]
// Make the navigation bar a subview of the current view controller
self.view.addSubview(navigationBar)
}
#pragma action method
func actionRefresh(sender: UIBarButtonItem)
{
print("The action button is refreshed")
}
Print statement is
The action button is refreshed
OBJECTIVE C
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UINavigationBar *navbar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 64)];
navbar.backgroundColor = [UIColor whiteColor];
navbar.delegate = self;
UINavigationItem * navItem = [[UINavigationItem alloc] init];
navItem.title = #"Title"; //Set Title Here Wahtever You Want Here
UIBarButtonItem *buttonRefresh = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
target:self
action:#selector(actionRefresh:)];
navItem.leftBarButtonItem = buttonRefresh;
navbar.items = #[navItem];
[self.view addSubview:navbar];
}
The NSLog statement is
The button action refresh is performed
See the refresh button in screenshot
Good Solutions
Add Default Icons to Navigation Bar
Navigation Bar Item Programmatically
Adding Navigation Bar item Programmatically
Instead of using .Plain, you should be using .Refresh.
let refreshButton = UIBarButtonItem(barButtonSystemItem: .Refresh, target: self, action: #selector(FollowVC.refresh))
Also you should be using the init(barButtonSystemItem:target:action:) instead of the init(title:style:target:action:).

How do I keep my navigation Bar and tableView separate as opposed to having my navBar on top of my tableView

I want it so that my navBar doesn't sit on top of my table view but instead is separate from it, so each tableView cell is displayed in equal proportions. As it is, I can't seem to change it, I have tried adding it manually, programtically and tried to change it in the view hierarchy, which I am unable to do. I imagine there is a straightforward solution to this I just can't work out what that is? Below is my code.
override func viewDidLoad() {
super.viewDidLoad()
let navigationBar = UINavigationBar(frame: CGRectMake(0, 0, self.view.frame.size.width, 44))
navigationBar.backgroundColor = UIColor.whiteColor()
navigationBar.delegate = self
let navigationItem = UINavigationItem()
navigationItem.title = "Title"
let leftButton = UIBarButtonItem(title: "Save", style: UIBarButtonItemStyle.Plain, target: self, action: "btn_clicked:")
let rightButton = UIBarButtonItem(title: "Right", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
navigationItem.leftBarButtonItem = leftButton
navigationItem.rightBarButtonItem = rightButton
navigationBar.items = [navigationItem]
self.view.addSubview(navigationBar)
}
I had the same problem. A solution is just using a standard view controller and then adding table view and navBag. Instead of trying to add a navBar on top of a tableviewcontroller.
Im quite new to swift but i hope this answer helps.

Add searchBar in navigationBar after viewDidLoad?

In my application, I want to have a search button in the navigation bar and when the button is pressed searchbar should appear in the Navigation Bar. I've seen many posts on the subject, but somehow it does not work for me.
So, I placed a SearchDisplayController right below nav bar. then in the viewDidLoad I assign an action to the search button and remove searchbar from superview. Once button is clicked, I am calling mapSearchDisplayController.displaysSearchBarInNavigationBar = true, but nothing happends. Code extracts below:
override func viewDidLoad() {
super.viewDidLoad()
banner.delegate = self
// Add button to navbar
var filterButton : UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Organize, target: self, action: nil)
self.navigationItem.leftBarButtonItem = filterButton
var aboutButton : UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: self, action: "aboutAction")
var searchButton : UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Search, target: self, action: "searchAction")
var rButtons : [UIBarButtonItem] = [aboutButton, searchButton]
self.navigationItem.rightBarButtonItems = rButtons
// Deal with Search Display Controller
self.mapSearchDisplayController.delegate = self.mapSearchDisplayController;
self.mapSearchDisplayController.searchResultsDataSource = self.mapSearchDisplayController;
self.mapSearchDisplayController.searchResultsDelegate = self.mapSearchDisplayController;
self.mapSearchDisplayController.searchBar.removeFromSuperview();
}
func searchAction(){
println("Search action")
mapSearchDisplayController.displaysSearchBarInNavigationBar = true
}
If I call displaysSearchBarInNavigationBar = true in viewDidLoad then searchBar correctly appears in the Navigation Bar.
How do I make appear in Nav bar on the button press?
Any help is appreaciated.
I created a search bar using
let searchBar = UISearchBar(frame : CGRect(0, 0, self.navigationController?.navigationBar.frame.size.width)! * 0.9, 0)
self.searchBar.placeholder = "Search"
self.searchBar.delegate = self
And then added it to the navigation bar as follows:
self.navigationItem.titleView = self.searchBar
Further styling etc can also be done but I just created and added it to the navbar on button pressed and removed it from superview when it needed to be hidden.

Resources