I have a tabBarController under which I loaded some navigation controller. But the title of my navigation controller is not showing up. Even I noticed if I add buttons in my left and right navbar item, it doesn't show up as well.
My Tabbar Setup:
let quranNavigationController = UINavigationController()
// quranNavigationController.navigationBar.titleTextAttributes = textAttributes
// quranNavigationController.navigationBar.tintColor = Colors.primaryTextColor
// quranNavigationController.navigationBar.barTintColor = Colors.navigationBackgroundPrimary
let quranSnackBarController = AppSnackbarController(rootViewController: quranNavigationController)
quranSnackBarController.shouldExtend = false
quranSnackBarController.tabBarItem = UITabBarItem(title: "Books".localized(), image: UIImage(named: "quran"), tag: 1);
let menuViewController = TestViewController()
let quranController = QuranPrintController()
let sideMenuController = SideMenuController(contentViewController: quranController, menuViewController: menuViewController)
quranNavigationController.viewControllers = [sideMenuController]
tabBarController.viewControllers = [homeNavigationController2, quranSnackBarController, prayerNavigationController, duaSnackBarController]
window.rootViewController = tabBarController
QuranPrintController:
class QuranPrintController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Quran"
self.navigationItem.title = "Prayer Times"
}
}
This is what my output is. No title is shown. I tried adding buttons on the left and right sides. But didn't work as well
First make sure your tabbarcontroller is embedded with navigation controller and then your all controllers are connected with your navbar
like this
then embed your navigation controllers with your each view controller with seperate navigController
Try Add this in your ViewdidLoad() .
self.view.bringSubviewToFront(yourbuttonname)
Related
I have subclassed UITabBarController to allow for some customization specific to my app. It is the root view controller of my UIWindow and displays itself correctly on launch, and even shows the correct tab's view hierarchy as well.
The problem is with the selected tabbar item's tint color. Inside viewDidLoad of the custom tab bar controller subclass, I have set both the unselected and selected tint colors for the tab bar. See below:
override func viewDidLoad() {
super.viewDidLoad()
tabBar.tintColor = .tabBarItemActiveTint
tabBar.unselectedItemTintColor = .tabBarItemInactiveTint
tabBar.barTintColor = .tabBarBg
let dashboardVC = DashboardViewController.build()
let settingsVC = SettingsTableViewController.build()
let settingsNavC = UINavigationController(rootViewController: settingsVC)
settingsNavC.navigationBar.barStyle = .black
viewControllers = [dashboardVC, settingsNavC]
selectedViewController = dashboardVC
// Accessing the view property of each tab's root view controller forces
// the system to run "viewDidLoad" which will configure the tab icon and
// title in the tab bar.
let _ = dashboardVC.view
let _ = settingsVC.view
}
As you can see, the controller has its child view hierarchies set, and the views are loaded at the bottom so their respective viewDidLoad methods run where I have code that sets the tabBarItem. Here's an example from the dashboard view controller:
tabBarItem = UITabBarItem(title: "Dashboard", image: UIImage(named: Theme.dashboardTabBarIcon), tag: 0)
Everything about this works except for the selected icon and title. When the app launches I can see the tab bar, the first view hierarchy (the dashboard) is visible onscreen and the tabs all function properly. But the dashboard's icon and title are in an unselected state. I have to actually tap the tab bar icon to get the state to change such that it is selected.
Once you tap one of the tabs, the selected state works as normal. The issue is only on the first presentation of the tab bar.
Here is an image showing the initial state of the tab bar on launch. Notice the dashboard icon is not selected, even though it is the presented view controller.
UPDATE
Skaal's answer below solved the problem for me.
For future reference: the key difference between the code presented here in my question and his sample in the answer is that the tabBarItem is set in viewDidLoad of his custom TabBarController class. By contrast, that code was placed within the viewDidLoad method of each constituent view controller class in my project. There must be a timing issue of when things are called that causes the tint color to not be set in one scenario and work properly in the other.
Key Takeaway: If you set up a tab bar controller programmatically, be sure to set your tabBarItem properties early on to ensure tint colors work properly.
You can use :
selectedIndex = 0 // the index of your dashboardVC
instead of selectedViewController
EDIT - Here is a working sample of UITabBarController:
class TabBarController: UITabBarController {
private lazy var firstController: UIViewController = {
let controller = UIViewController()
controller.title = "First"
controller.view.backgroundColor = .lightGray
return controller
}()
private lazy var secondController: UIViewController = {
let controller = UIViewController()
controller.title = "Second"
controller.view.backgroundColor = .darkGray
return controller
}()
private var controllers: [UIViewController] {
return [firstController, secondController]
}
override func viewDidLoad() {
super.viewDidLoad()
tabBar.tintColor = .magenta
tabBar.unselectedItemTintColor = .white
tabBar.barTintColor = .black
firstController.tabBarItem = UITabBarItem(title: "First", image: UIImage(), tag: 0) // replace with your image
secondController.tabBarItem = UITabBarItem(title: "Second", image: UIImage(), tag: 1) // replace with your image
viewControllers = controllers
selectedViewController = firstController
}
}
I am still fairly new to xcode.
I am trying to programatically change the navigation title when different tabs are selected in my UITabBarController.
I have a UItabBarController that creates the tab bar, then I have separate UIViewControllers which have different content for each of the tabs - this part works fine, however I cannot get the navigation title to change when different tabs are selected.
Here is the code for the main tab controller.
// SUPER VIEW DID LOAD
override func viewDidLoad() {
super.viewDidLoad()
// NAVIGATION ITEM
navigationItem.title = "Job Information"
navigationController?.navigationBar.prefersLargeTitles = true
//setup our custom view controllers
let jobInfo = page_jobInfo()
let shots = page_shotList()
let attachments = page_attachments()
let notes = page_notes()
jobInfo.tabBarItem.title = "Information"
jobInfo.tabBarItem.image = UIImage(named: "jobInfo")
shots.tabBarItem.title = "Shots"
shots.tabBarItem.image = UIImage(named: "shots")
attachments.tabBarItem.title = "Attachments"
attachments.tabBarItem.image = UIImage(named: "attachments")
notes.tabBarItem.title = "Notes"
notes.tabBarItem.image = UIImage(named: "notes")
viewControllers = [jobInfo, shots, attachments, notes]
}
Here is the code for the second tab button - The other 2 tabs are the same as this so didn't want to spam this feed with huge amounts of code.
// SUPER VIEW DID LOAD
override func viewDidLoad() {
super.viewDidLoad()
// NAVIGATION ITEM
navigationItem.title = "Shot List"
navigationController?.navigationBar.prefersLargeTitles = true
}
Since your view controllers are embedded in UITabBarController, you should change its (tab bar controller's) navigationItem. Moreover, you should do that in viewWillAppear method instead of viewDidLoad, like so:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.navigationItem.title = "Bookmarks"
}
I know this question gets asked a lot.
I've tried every answer (I think) and can't get a title to show up.
I have a static method I use to show view controllers modally.
I think I understand that a navigation controller gets its title from the title property of the view controller it is presenting, but I cannot get my vc's title to show up, and other methods I have tried aren't working, either.
static func present(vc vc: UIViewController) {
// The navCtrl presents a vc, and uses that title.
// I should be able to set this, right?
vc.title = "vc.title" // doesn't show up
vc.navigationItem.title = "vc.navigationItem.title" // nothing
vc.navigationItem.prompt = "vc.navigationItem.prompt" // doesn't show
vc.navigationController?.title = "vc.navigationController?.title" // nuttin'
let navCtrl = UINavigationController(rootViewController: vc)
navCtrl.navigationBar.tintColor = UIColor.whiteColor()
navCtrl.navigationBar.barTintColor = UIColor.blackColor()
navCtrl.navigationBar.translucent = false
// How about adding a UINavigationItem? Nope.
// let item = UINavigationItem(title: "UINavigationItem")
// navCtrl.navigationBar.pushNavigationItem(item, animated: true) // CRASH: Cannot call pushNavigationItem:animated: directly on a UINavigationBar managed by a controller.
// Can I set something on the navCtrl? Huh-uh. None of this works
navCtrl.navigationController?.title = "navCtrl.navigationController?.title"
navCtrl.navigationItem.prompt = "navCtrl.navigationItem.prompt"
navCtrl.title = "navCtrl.title"
navCtrl.navigationItem.title = "navCtrl.navigationItem.title"
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(navCtrl, animated: true, completion: nil)
}
No matter what I've tried, I just get an empty navigation bar with a close button:
Im trying to process a navigation inside a reusble func i cannot get it to work this is the code i have so far.
static func navigationBarShow() {
let navigationCoontroller = UINavigationController()
navigationCoontroller.navigationBarHidden = false
navigationCoontroller.navigationBar.barTintColor = UIColor(red:0.4, green:0.76, blue:0.93, alpha:1.0)
navigationCoontroller.navigationBar.translucent = false
navigationCoontroller.title = "Signup"
navigationCoontroller.navigationBar.tintColor = UIColor.whiteColor()
navigationCoontroller.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
}
Try writing it as an extension to UINavigationController and use self as the navigation controller. You are creating a new UINavigationController instance each time you want to display a navigation bar and that instance is never being displayed on the screen.
extension UINavigationController {
func showNavigationBar() {
self.navigationBarHidden = false
self.navigationBar.barTintColor = UIColor(red:0.4, green:0.76, blue:0.93, alpha:1.0)
self.navigationBar.translucent = false
self.title = "Signup"
self.navigationBar.tintColor = UIColor.whiteColor()
self.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
}
}
Then, from any UINavigationController, you can call showNavigationBar().
Update:
In the code for any subclass of UIViewController that is embedded in a UINavigationController, call navigationController!.showNavigationBar().
For example:
class MyViewController: UIViewController {
override func viewDidLoad() {
self.navigationController!.showNavigationBar()
}
}
Note that the ! assumes your view controller is embedded in a navigation controller. If any vc is not embedded in a navigation controller but you want a navigation bar, you should consider embedding it in a navigation controller.
This line:
let navigationCoontroller = UINavigationController()
creates a brand-new navigation controller every time you run it.
Unless the code you posted is run once and only once, that's wrong, since every time you call that function you create a new navigation controller
I am performing a segue from my loadVC to containterVC in which I set up a navigationController and set it's rootViewController to mainVC
Code in viewDidLoad in containterVC:
override func viewDidLoad() {
super.viewDidLoad()
mainVC = UIStoryboard.mainVC() //This is an extension to UIStoryboard
//Setting up the delegate:
mainVC.delegate = self
//rootViewController - ten najbardziej na dole
myNavigationController = UINavigationController(rootViewController: mainVC)
//Storing the root view as currentViewController:
self.currentViewController = mainVC
myNavigationController.addChildViewController(mainVC)
self.view.addSubview(myNavigationController.view)
addChildViewController(myNavigationController)
myNavigationController.didMoveToParentViewController(self)
//Trying to set up the navigation bar
let bar = myNavigationController.navigationBar
//Navigation bars:
bar.barTintColor = UIColor.blackColor()
bar.tintColor = UIColor.whiteColor()
bar.translucent = false
}
I launch the project. And? Everything works properly.
Then I try to add these under "bar.translucent = false" line:
print("statement1")
let menuButton = UIBarButtonItem(title: "Menu", style: UIBarButtonItemStyle.Plain, target: self, action: "")
print("statement2")
let item = myNavigationController.navigationItem
print("statement3")
item.leftBarButtonItem = menuButton
print("statement4")
bar.items = [item]
print("statement5")
After launching the project print statements up to 4 are displayed and the 5th is not. So it seems that the segue between loadVC and containterVC is done, but I don't see the mainVC screen that was set up as a rootViewController.
When I delete "bar.items = [item]" line the project is run as it should be, but there is no "Menu" button in the navigation bar.
What am I doing wrong?
You can just use a "container view" from the storyboard and embed a UINavigationController with your mainVC directly within the storyboard.
Anyway i think that myNavigationController.addChildViewController(mainVC) not necessary.
Also the bar items should be set to the mainVC's navigationItem, not the navigationController's one.
Also you did not mention what kind of segue are you using.