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"
}
Related
I added a tab bar controller of 8 items, but the system adds the 'more' button for me.
The problem is I can't change the title of tab bar item 5 and 'more'.
Here is the error message. I have confirmed that I have 8 Items.
Code :
tabBarController?.tabBar.items![5].title = "ok"
Error
Thread 1: Exception: "*** __boundsFail: index 5 beyond bounds [0 .. 4]"
Consider the following code:
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
configureViewControllers()
}
private func configureViewControllers() {
let colors: [UIColor] = [.systemRed, .systemBlue, .systemGray, .systemTeal, .systemPink]
var vcs = [UIViewController]()
for i in 0...6 {
let vc = UIViewController()
vc.view.backgroundColor = colors.randomElement()!
vc.tabBarItem.title = "VC \(i)"
vcs.append(vc)
}
viewControllers = vcs
}
}
So you have to set the titles of the view controllers via vc.tabBarItem.title = "your title" or you can set them even inside of your view controllers viewDidLoad() with tabBarItem.title = "...".
For further reading: https://developer.apple.com/documentation/uikit/uitabbarcontroller
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)
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 have following code in class homeVC: UICollectionViewController to display the title in the navigation bar and it works as expected.
override func viewDidLoad() {
super.viewDidLoad()
.
.
.
self.navigationItem.title = PFUser.current()?.username?.uppercased()
.
.
}
But when I clicked on the button to go to another view controller and then came back to homeVC view controller self.navigationItem.title is not displaying anything. I'mm wondering why that happened?
The following code is to go to another view controller
#objc func followersTap() {
category = "followers"
// make references to followersVC
let followers = self.storyboard?.instantiateViewController(withIdentifier: "followersVC") as! followersVC
// present
self.navigationController?.pushViewController(followers, animated: true)
}
This is the view controller to go to , and in this view controller i don't want to show the title from previous view controller so I'm using self.navigationController!.navigationBar.topItem!.title = "" to make it empty and when I go back to previous view controller the title is also empty, why?
class followersVC: UITableViewController{
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController!.navigationBar.topItem!.title = ""
self.tableView.reloadData()
}
I am trying to not show the first view controller title on second view controller top left corner where back button is and keep first and second view controller title shows.
If your plan is to not show the title from a previous view controller, the solution is like this:
Change:
self.navigationItem.title = PFUser.current()?.username?.uppercased()
to:
self.title = PFUser.current()?.username?.uppercased()
And change:
self.navigationController!.navigationBar.topItem!.title = ""
to:
self.title = ""
Try to move your self.navigationItem.title = PFUser.current()?.username?.uppercased() in viewDidAppear(), this should help
I have a tab bar controller with four tabs. I want to show the first item at the beginning. With a button click from the first item (view), when it is clicked, I want to show the second tab. How can I do that?
I created a custom tabbarController class and tried to give tabbarindex like below. I checked at the beginning without a button click but it didn't work. It always loads the first tab bar item.
class HTabViewController: UITabBarController, UITabBarControllerDelegate {
var controllerArray : [UIViewController] = []
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.selectedIndex = 2
self.tabBar.tintColor = UIColor.red
// defineViewController()
}
}
Note : can we show specific tab item with a button click?
Since self is the UITabBarController, you need to set the selectedIndex on self, not self.tabBarController.
override func viewDidLoad() {
super.viewDidLoad()
selectedIndex = 2
tabBar.tintColor = UIColor.red
}
job done, add self.selectedIndex = needed_index at viewDidLoad() method