On my main navigationController, there is a right bar button called "Next Page". When the button is pressed, it calls the method called "nextPage()" which initializes the navigation controller and show it.
The code for nextPage() is like following:
func nextPage() {
let window = UIWindow(frame: UIScreen.mainScreen().bounds)
let CustomLoginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("viewControllerID") as! customVC
let navVC = UINavigationController.init(rootViewController: CustomLoginVC)
navVC.view.autoresizingMask = [.FlexibleHeight, .FlexibleWidth, .FlexibleTopMargin, .FlexibleLeftMargin]
navVC.navigationBar.translucent = false
navVC.navigationItem.title = "haha"
navVC.navigationBar.tintColor = UIColor.whiteColor()
navVC.navigationBar.titleTextAttributes = [NSFontAttributeName: UIFont(name: "AvenirNext-Medium", size: 22)!, NSForegroundColorAttributeName: UIColor.whiteColor() ]
navVC.navigationItem.leftBarButtonItem?.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "AvenirNext", size: 18)!], forState: UIControlState.Normal)
let backButton = UIBarButtonItem.init(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "backButtonPressedInPDF")
let exportButton = UIBarButtonItem.init(image: UIImage(named: "export"), style: UIBarButtonItemStyle.Plain, target: self, action: "saveAsPDF")
navVC.navigationItem.setLeftBarButtonItem(backButton, animated: false)
navVC.navigationItem.setRightBarButtonItem(exportButton, animated: false)
window.rootViewController = navVC
self.presentViewController(navVC, animated: true, completion: nil)
}
As you can see I'm instantiating CustomLoginVC which is a type of customVC from Main storyboard. customVC is a subclass of UIViewController. Then, initialize UINavigationController with CustomLoginVC and assign left and right bar button items. However, title and bar button items are not shown on the nav bar like below image.
I'm not understanding why bar button items and title are not made on the nav bar.
Also in AppDelegate, I set the method like following:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
UINavigationBar.appearance().barTintColor = UIColor(hex: "00BFA5")
application.statusBarStyle = UIStatusBarStyle.LightContent
return true
}
Any comments are appreciated!
You need to set the title and buttons on CustomLoginVC and not on navVC
I think you should write to below three line try it:
navVC.navigationItem.leftBarButtonItem = nil;
navVC.navigationItem.rightBarButtonItem = nil;
navVC.navigationItem.hidesBackButton = true;
after that try to write:
navVC.navigationItem.setLeftBarButtonItem(backButton, animated: false)
navVC.navigationItem.setRightBarButtonItem(exportButton, animated: false)
OR
self.title = "Your Title"
var homeButton : UIBarButtonItem = UIBarButtonItem(title: "LeftButtonTitle", style: UIBarButtonItemStyle.Plain, target: self, action: "")
var logButton : UIBarButtonItem = UIBarButtonItem(title: "RigthButtonTitle", style: UIBarButtonItemStyle.Plain, target: self, action: "")
self.navigationItem.leftBarButtonItem = homeButton
self.navigationItem.rightBarButtonItem = logButton
Related
Our application has a deployment target of iOS 10. We're hiding all back button titles (for the entire app) with the following code
let attributes: [NSAttributedString.Key : Any] = [
.font : UIFont.systemFont(ofSize: 0.001),
.foregroundColor: UIColor.clear
]
let barButtonItemAppearance = UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self])
barButtonItemAppearance.setTitleTextAttributes(attributes, for: .normal)
barButtonItemAppearance.setTitleTextAttributes(attributes, for: .highlighted)
This worked up until iOS 13, where the back button titles are no longer hidden.
I saw the WWDC 2019 video about the new apperance APIs, but as far as I can tell it only told me how to use the new APIs for a single navigation bar (and not for the entire app).
How can I achieve this?
Add in viewDidLoad() method of the parent(previous in the stack) controller.
self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)
In the next screen, only the arrow image will be presented.
or you can put this code before pushViewController method, for example
func presentNextScreen(_ controller: UIViewController){
// Suppress title in the back button on the next screen.
self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)
self.navigationController?.pushViewController(controller, animated: true)
}
For me, the easiest way to hide the title in the back button is to configure the appearance of UINavigationBar
if #available(iOS 13.0, *) {
let standartAppearence = UINavigationBarAppearance()
standartAppearence.configureWithDefaultBackground()
let backButtonAppearence = UIBarButtonItemAppearance()
let titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.clear]
backButtonAppearence.normal.titleTextAttributes = titleTextAttributes
backButtonAppearence.highlighted.titleTextAttributes = titleTextAttributes
standartAppearence.backButtonAppearance = backButtonAppearence
UINavigationBar.appearance().standardAppearance = standartAppearence
UINavigationBar.appearance().compactAppearance = standartAppearence
UINavigationBar.appearance().scrollEdgeAppearance = standartAppearence
}
In addition, here you can add any other configuration of the navigation bar
A workaround:
Create a base class: BaseViewController.
class BaseViewController: UIViewController {
func hideBackButton() {
self.navigationItem.leftBarButtonItem = nil
}
func hideCloseButton() {
self.navigationItem.rightBarButtonItem = nil
}
override public func viewDidLoad() {
super.viewDidLoad()
addNavigationButtons()
}
func addNavigationButtons() {
let backButton = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(goBack))
self.navigationItem.leftBarButtonItem = backButton
let closeButton = UIBarButtonItem(image: UIImage(named: "close"), style: .plain, target: self, action: #selector(closeTheFlow))
self.navigationItem.rightBarButtonItem = closeButton
}
#objc func goBack() {
//Go Back
}
#objc func closeTheFlow() {
//Close
}
Make every ViewController a subclass of BaseViewController.
You could do anything with the right and left buttons in the entire app.
I hide title gloabal. a trick
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffset(horizontal: -UIScreen.main.bounds.size.width, vertical: 0), for: UIBarMetrics.default)
I'm relatively new at iOS. I'm struggling, for a while now with this issue. I don't know how to set the logic for presenting popUp when user taps on right bar button item. Basically, it should look like this:PopUp I searched through Google, but I didn't have any luck. I would appreciate if someone would help me with some code.
//My VC
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let rightBarButtonItem = UIBarButtonItem(title: "Share", style: .plain, target: self, action: #selector(clickShare))
rightBarButtonItem.tintColor = UIColor.black
navigationItem.rightBarButtonItem = rightBarButtonItem
// navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Share", style: UIBarButtonItemStyle.plain, target: self, action: #selector(clickShare))
navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "backArrow"), style: UIBarButtonItemStyle.plain, target: self, action: #selector(goBack))
UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedStringKey.font : UIFont(name: "OpenSans", size: 14)! ], for: .normal)
}
//MARK: - Actions
#objc func goBack() {
navigationController?.popViewController(animated: true)
}
#objc func clickShare() {
//this is where the logic should go
}
//This is my storyboard:
Storyboard
Add following action,
#IBAction func yourButtonClickAction(sender: UIBarButtonItem) {
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("YourViewController") as! UIViewController
vc.modalPresentationStyle = UIModalPresentationStyle.Popover
let popover: UIPopoverPresentationController = vc.popoverPresentationController!
popover.barButtonItem = sender
popover.delegate = self
presentViewController(vc, animated: true, completion:nil)
}
Add this action to you barButtonItem.
'YourViewController' = controller consisting of Public, followers options.
I have viewController. Inside is I have UIView
lazy var cView : UIView = {
var view = UIView()
view.backgroundColor = .red
return view
}()
Inside this view I have UINavigationBar
lazy var navigationBar : UINavigationBar = {
let bar = UINavigationBar()
let leftButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.done, target: self, action: #selector(cancel))
bar.topItem?.setLeftBarButton(leftButton, animated: true)
let rightButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(done))
bar.topItem?.setRightBarButton(rightButton, animated: true)
bar.barTintColor = .green
bar.tintColor = UIColor.red
bar.barStyle = .default
bar.isTranslucent = false
return bar
}()
The problem is that in viewController I see only red view with green bar and without any buttons.
What am I doing wrong ? How to make buttons visible ?
bar.topItem UINavigationItem is nil when UINavigationBar is initialized. You can use bar.setItems(items: [UINavigationItem]?, animated: Bool) method to set bar.topItem
I have done the following customisation to my embedded UINavigationcontroller. I've done this in the view controller of the view that will show up as first.
However I'm trying to clean it up so that I don't have this all in my UIView class by creating a separate class that will take care of this. The code I'm currently using
self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: "navigation.background"), for: .default)
let backButton = UIImage(named: "Back.button")?.withRenderingMode(.alwaysOriginal)
let backButtonHigh = UIImage(named: "Back.button.highlighted")?.withRenderingMode(.alwaysOriginal)
self.navigationController?.navigationBar.backIndicatorImage = backButton
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = backButtonHigh
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
What I've tried to do is extend the UInavigationcontroller in a new class like this
class RSRNavigationController: UINavigationController{
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: "navigation.background"), for: .default)
let backButton = UIImage(named: "Back.button")?.withRenderingMode(.alwaysOriginal)
let backButtonHigh = UIImage(named: "Back.button.highlighted")?.withRenderingMode(.alwaysOriginal)
self.navigationController?.navigationBar.backIndicatorImage = backButton
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = backButtonHigh
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
}
this doesn't work. It will run without problems but it won't actually do anything.
I've also tried to do the following
class RSRNavigationController: UINavigationBar{
override func draw(_ rect: CGRect) {
super.draw(rect)
self.setBackgroundImage(UIImage(named: "navigation.background"), for: .default)
let backButton = UIImage(named: "Back.button")?.withRenderingMode(.alwaysOriginal)
let backButtonHigh = UIImage(named: "Back.button.highlighted")?.withRenderingMode(.alwaysOriginal)
self.backIndicatorImage = backButton
self.backIndicatorTransitionMaskImage = backButtonHigh
//self.backItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
However I can't seem to set the title for the back button.
Does anyone know how to fix this?
Your problem lies here, when you reference navigationController INSIDE your custom navigationController class
Instead of doing
self.navigationController?.navigationBar.backIndicatorImage = backButton
do this
self.navigationBar.backIndicatorImage = backButton
Reason?
Because when you extend your custom class by UINavigationController, it becomes a navigationController itself. And by doing self.navigationController you are telling your app to look for a navigationController within which your custom navigationCOntroller resides. Ofcourse such a nav controller does not exist because your custom navController is the main or the top navController of the app. So just remove the self.navigationController part from your custom class, the rest of the code that you have written in your viewDidLoad should work good.
If you still have any questions feel free to ask
You do not change these properties in the navigation controller itself, you change it in the viewController that is embedded inside a navigation controller.
These customization has to be done in a parent ViewController of your view controllers.
This Answer has more info:
https://stackoverflow.com/a/16913435/4004429
if you just want to custom the backButton of the navigationBar,you can add this code in your child view controller :
func setupLeftBarItem() -> Void {
let originalImage = UIImage.init(named: "leftBatItem")?.withRenderingMode(.alwaysOriginal)
let leftBarItem = UIBarButtonItem.init(image: originalImage, style: .done, target: self, action: #selector(leftBarButtonItemDidTouch))
navigationItem.leftBarButtonItem = leftBarItem
}
func leftBarButtonItemDidTouch() -> Void {
_ = navigationController?.popViewController(animated: true)
}
I am trying to follow this tutorial, this answer, and this answer to create navigation bars for each of my tabs in a tab-based application in iOS 8 / Swift, but no title or buttons on my navigation bar are showing.
Here is what I have so far:
// AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let tabBarController = UITabBarController()
let vc1 = ViewController()
let vc2 = ViewController()
let vc3 = ViewController()
let nc1 = UINavigationController(rootViewController: vc1)
let nc2 = UINavigationController(rootViewController: vc2)
let nc3 = UINavigationController(rootViewController: vc3)
let controllers = [nc1,nc2,nc3]
tabBarController.viewControllers = controllers
nc1.tabBarItem = UITabBarItem(title: "item1", image: nil, tag: 1)
nc2.tabBarItem = UITabBarItem(title: "item2", image: nil, tag: 1)
nc3.tabBarItem = UITabBarItem(title: "item3", image: nil, tag: 1)
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = tabBarController
window?.makeKeyAndVisible()
return true
}
// ViewController.swift
class ViewController: UIViewController, UINavigationBarDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let navigationBar = UINavigationBar(frame: CGRectMake(0, 0, self.view.frame.size.width, 44))
navigationBar.backgroundColor = UIColor.blueColor()
navigationBar.delegate = self;
let navigationItem = UINavigationItem()
navigationItem.title = "Title"
let leftButton = UIBarButtonItem(title: "Left Button", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
let rightButton = UIBarButtonItem(title: "Right Button", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
navigationItem.leftBarButtonItem = leftButton
navigationItem.rightBarButtonItem = rightButton
navigationBar.items = [navigationItem]
}
func positionForBar(bar: UIBarPositioning) -> UIBarPosition {
return UIBarPosition.TopAttached
}
}
But I am just getting a blank navigation bar on top in the simulator.
You're making a custom UINavigationBar when one is already provided to you with the UINavigationController.
Try this instead in your ViewController:
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Title"
let navigationBar = navigationController!.navigationBar
navigationBar.tintColor = UIColor.blueColor()
let leftButton = UIBarButtonItem(title: "Left Button", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
let rightButton = UIBarButtonItem(title: "Right Button", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
navigationItem.leftBarButtonItem = leftButton
navigationItem.rightBarButtonItem = rightButton
}
No need to use a new navigation bar just use your existent navigation bar. Remember what you did here :
let nc1 = UINavigationController(rootViewController: vc1)
So your view controller is already embed inside a navigation controller just use self to access to the navigation items
self.title = "Your Title"
var homeButton = UIBarButtonItem(title: "LeftButton", style: .Plain, target: self, action: "")
var logButton = UIBarButtonItem(title: "RigthButton", style: .Plain, target: self, action: "")
self.navigationItem.leftBarButtonItem = homeButton
self.navigationItem.rightBarButtonItem = logButton
I was unnecessarily creating two navigation bars. The navigation controller comes with a navigation bar, and I changed my ViewController to:
class ViewController: UIViewController, UINavigationBarDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "My Title"
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Left Button", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Right Button", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
}
func positionForBar(bar: UIBarPositioning) -> UIBarPosition {
return UIBarPosition.TopAttached
}
}