The following code in my appDelegate works for Objective-C to show selected state of custom UITabBar Items. Despite my best efforts, I cannot figure out how to translate this code to Swift. Can someone point me in the right direction?
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
UITabBar *tabBar = tabBarController.tabBar;
UITabBarItem *tabBarItem1 = [tabBar.items objectAtIndex:0];
UITabBarItem *tabBarItem2 = [tabBar.items objectAtIndex:1];
UITabBarItem *tabBarItem3 = [tabBar.items objectAtIndex:2];
UITabBarItem *tabBarItem4 = [tabBar.items objectAtIndex:3];
[[UITabBar appearance] setTintColor:[UIColor colorWithRed:0.0 green:122.0/255.0 blue:1.0 alpha:1.0]]; //make all text and icons in tab bar the system blue font
tabBarItem1.selectedImage = [UIImage imageNamed:#"815-car-selected#2x.png"];
tabBarItem2.selectedImage = [UIImage imageNamed:#"742-wrench-selected#2x.png"];
tabBarItem3.selectedImage = [UIImage imageNamed:#"710-folder-selected#2x.png"];
tabBarItem4.selectedImage = [UIImage imageNamed:#"724-info-selected#2x.png"];
Thank you.
OK, so first off, I assume you're setting your Image and Selected Image in your Story Board, and are running into the issue where the selected image doesn't show up (based on the code sample you provided). Here's what I have in Swift 1.2 (I assume this all works in earlier versions as well). Its based on the response from ad121, but with changes I needed to make it work correctly. And note, you'll want this in your AppDelegate in case you're unsure where this goes.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
// Type casting in swift is "as Type", you'll need to unwrap optionals however.
let tabBarController = self.window!.rootViewController as! UITabBarController
let tabBar = tabBarController.tabBar as UITabBar
// I prefer to use 0 based labels since the array is 0 based
let tabBarItem0 = tabBar.items![0] as! UITabBarItem
let tabBarItem1 = tabBar.items![1] as! UITabBarItem
let tabBarItem2 = tabBar.items![2] as! UITabBarItem
let tabBarItem3 = tabBar.items![3] as! UITabBarItem
// The UIColor method you are using is an initializer in swift
tabBar.barTintColor = UIColor(red: 0.0, green: 122.0/255.0, blue: 1.0, alpha: 1.0)
// Using Assets with the various sizes loaded (1x, 2x, 3x) is better.
tabBarItem0.selectedImage = UIImage(named: "815-car-selected")
tabBarItem1.selectedImage = UIImage(named: "742-wrench-selected")
tabBarItem2.selectedImage = UIImage(named: "710-folder-selected")
tabBarItem3.selectedImage = UIImage(named: "724-info-selected")
return true
}
I recommend just looking at the documentation in XCode. All documentation is written in Swift and Objective C so it is very easy to translate between the two languages. Also read apple's swift basics to understand this code translation better: https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_467
Translation:
// Type casting in swift is "as Type"
tabBarController = self.window.rootViewController as UITabBarController
tabBar = tabBarController.tabBar
// Retrieving array values at indices can be shortened as array[index]
tabBarItem1 = tabBar.items[0] as UITabBarItem
tabBarItem2 = tabBar.items[1] as UITabBarItem
tabBarItem3 = tabBar.items[2] as UITabBarItem
tabBarItem4 = tabBar.items[3] as UITabBarItem
// The UIColor method you are using is an initializer in swift
tabBar.barTintColor = UIColor(red: 0.0, green: 122.0/255.0, blue: 1.0, alpha: 1.0)
// UIImage also has an initializer for your situation in swift
tabBarItem1.selectedImage = UIImage(named: "815-car-selected#2x.png")
tabBarItem2.selectedImage = UIImage(named: "742-wrench-selected#2x.png")
tabBarItem3.selectedImage = UIImage(named: "710-folder-selected#2x.png")
tabBarItem4.selectedImage = UIImage(named: "724-info-selected#2x.png")
Maybe you should use image and selected image.
So have 2 different images use one for normal and selected
tabBarItem.image = UIImage(named:"ImageName")
and
tabBarItem.selectedImage = UIImage(named:"ImageName")
That way when the tab is selected it will use selectedImage. If it's not selected it will use the normal image.
Related
I have UITabBar controller
let tabBarController = UITabBarController()
tabBarController.viewControllers = [todayViewController, forecastViewController]
window.rootViewController = tabBarController
window.makeKeyAndVisible()
tabBarController.selectedIndex = 0
inside todayViewController:
tabBarItem = UITabBarItem(title: "Today", image: #imageLiteral(resourceName: "TodayTabBarItem"), selectedImage: #imageLiteral(resourceName: "SunTabBarItemSelected"))
inside forecastViewController:
tabBarItem = UITabBarItem(title: "Forecast", image: #imageLiteral(resourceName: "ForecastTabBarItem"), selectedImage: #imageLiteral(resourceName: "ForecastTabBarItemSelected"))
When I start the app UITabBarItem of the first view controller is inactive. When I tap on it or on another one it becomes active (highlighted text and right image)
What should I do to make UITabBarItem active on app start?
Try tabBarItem = UITabBarItem not during the call to viewDidLoad, but when creating ViewContrller - in init
I want to create tab bar dynamically based on server response. Tab count will change every time. And how to design the views all view have the same design only data will change
suppose you have vc1,vc2,vc3
self.tabBarController.viewControllers = [vc1,vc2,vc3]
Create a separate class for tab bar controller. Create a method there which must return tab bar controller.
In the method, pass an array, on each index it will contains the tab bar name, image, selected image, view controller.
You'll need to make your server call BEFORE you set up the view controller. If it is your first view, you will need to do this in viewdidload and perhaps set up an activity indicator. If not you need to have some sort of loading screen / make your call in the immediately prior to your tabBar.
Put This Method in Utilities Class :
class func setupTabBarController(tabbarController: UITabBarController) {
let hOmeVC = HomePageViewController()
let skriblBoxVC = MySkribViewController()
let searchVC = SearchViewController()
tabbarController.tabBar.isExclusiveTouch = true
tabbarController.view.backgroundColor = UIColor.white
// Creating navigation Controller and putting them in tabBarController because without it we will not be able to push viewController
let homeNavigationController = UINavigationController()
let skriblBoxNavigationController = UINavigationController()
let searchNavigationController = UINavigationController()
tabbarController.viewControllers = []
tabbarController.tabBar.isTranslucent = false
tabbarController.viewControllers = [homeNavigationController, skriblBoxNavigationController, searchNavigationController]
tabbarController.selectedIndex = 0
tabbarController.tabBar.items![0].image = #imageLiteral(resourceName: "tab_home")
tabbarController.tabBar.items![1].image = #imageLiteral(resourceName: "tab_box")
tabbarController.tabBar.items![SBModules.SEARCH.rawValue].image = #imageLiteral(resourceName: "tab_search")
tabbarController.tabBar.items![2].image = #imageLiteral(resourceName: "tab_cart")
tabbarController.tabBar.items![0].selectedImage = #imageLiteral(resourceName: "tab_home_selected")
tabbarController.tabBar.items![1].selectedImage = #imageLiteral(resourceName: "tab_box_selected")
tabbarController.tabBar.items![2].selectedImage = #imageLiteral(resourceName: "tab_search_selected")
tabbarController.tabBar.barTintColor = UIColor.white
tabbarController.tabBar.tintColor = UIColor.tabBarBadgeColorWithAlpha()
tabbarController.tabBar.itemPositioning = .automatic
tabbarController.tabBar.itemSpacing = 2.0
tabbarController.tabBarItem.title = nil
if let items = tabbarController.tabBar.items {
for item in items {
item.title = ""
item.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0);
}
}
}
and class this method form viewController
Like
let tabbarController = UITabBarController()
func loadHomePage() {
Utilities.setupTabBarController(tabbarController: self.tabbarController)
self.updateBadgeValueToCart()
self.window?.rootViewController = self.tabbarController
}
I am using UITabBarController with 5 ViewController each ViewController have own UINavigationController as below:
I have added tabar image like
As seen from above image when TabBarItem is selected just blue image i can see...i wanted to show original image for selected tabaritem.
I had seen the example of setting property UIImageRenderingModeAlwaysOriginal. but i can not see anything on story board.
Below is the way I push TabBarController:
HomeViewController *vcHome = (HomeViewController*)[[UIStoryboard storyboardWithName:#"NexTabBar" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"ID_HOME_VC"];
vcHome.delegate = self;
[self.navigationController pushViewController:vcHome animated:YES];
How can I use the property UIImageRenderingModeAlwaysOriginal here so that I can see original images when particular TabBarItem is selected?
or if any other way is there with ios10.
Here is how I create tabBarItem for myTabBar
let storyboard = UIStoryboard(name: storyboardIdentifier, bundle: nil)
let vc:UIViewController? = storyboard.instantiateInitialViewController();
let selectedImage = UIImage(named: imageName)
let notSelectedImage = UIImage(named:selectedImageName)?.withRenderingMode(.alwaysOriginal)
let item = UITabBarItem(title: title, image: notSelectedImage, selectedImage: selectedImage)
vc!.tabBarItem = item
Objective C version:
UIStoryboard *sb = [UIStoryboard storyboardWithName:storyboardIdentifier bundle:nil];
UIViewController* vc = sb.instantiateInitialViewController;
UIImage* selectedImage = [[UIImage imageNamed:image] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage* notSelectedimage = [[UIImage imageNamed:selectedImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UITabBarItem* item = [[UITabBarItem alloc]initWithTitle:title image:notSelectedimage selectedImage:selectedImage];
[[UITabBar appearance] setSelectedImageTintColor:[UIColor whiteColor]];
vc.tabBarItem = item;
return vc;
If this did not help try to change also tabBar tints colors
self.tabBar.barTintColor = .orange
// set color of selected icons and text to white
self.tabBar.tintColor = .white
UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.white], for: .selected)
// set color of unselected text to gray
UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.gray], for: .normal)
I'm developing an app that uses both a Tab Bar and a Nav Bar. Right now, both of these display on the first page that loads for the app, but only the Tab Bar displays when I navigate to different tabs.
My issue is that I'm not entirely sure where the Nav Bar is actually being told to display. I saw posts about having to tie your nav bar and tab bar together, but I didn't fully understand them, and trying to implement them caused my app to not load at all. Should I be instantiating the Nav Bar in each view controller?
This is my AppDelegate:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Initialize the window
window = UIWindow.init(frame: UIScreen.mainScreen().bounds)
// Set Background Color of window
window?.backgroundColor = UIColor.whiteColor()
// Make the window visible
window!.makeKeyAndVisible()
// Create TabBarController
let tabBarController = CustomTabBarController()
window?.rootViewController = tabBarController
return true
}
This is my CustomTabBarController.swift:
override func viewWillAppear(animated: Bool) {
// color TabBar correctly
let darkTeal = UIColor(red:0.09, green:0.62, blue:0.56, alpha:1.0)
let lightTeal = UIColor(red:0.6, green:0.78, blue:0.74, alpha:1.0)
UITabBar.appearance().barTintColor = darkTeal
UITabBar.appearance().tintColor = UIColor.whiteColor()
UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.whiteColor()], forState:.Normal)
// customize TabBarItem width
let tabBarItemWidth = UIScreen.mainScreen().bounds.width / CGFloat(4)
UITabBar.appearance().selectionIndicatorImage =
UIImage().makeImageWithColorAndSize(lightTeal, size: CGSize(width: tabBarItemWidth, height: 49.0))
// create Tab Bar items
let findOutVC = FindOut()
let goOutVC = GoOut()
let speakOutVC = SpeakOut()
let reachOutVC = ReachOut()
// images
let findout = UIImage(named: "find_out")
let goout = UIImage(named: "go_out")
let speakout = UIImage(named: "speak_out")
let reachout = UIImage(named: "reach_out")
// modify tabBar items
findOutVC.tabBarItem = UITabBarItem(
title: "Find Out",
image: findout,
tag: 1)
goOutVC.tabBarItem = UITabBarItem(
title: "Go Out",
image: goout,
tag: 2)
speakOutVC.tabBarItem = UITabBarItem(
title: "Speak Out",
image: speakout,
tag: 3)
reachOutVC.tabBarItem = UITabBarItem(
title: "Reach Out",
image: reachout,
tag: 4)
// set up tabBar items
let tabs = [findOutVC, goOutVC, speakOutVC, reachOutVC]
self.viewControllers = tabs
}
And this is my CustomNavBarController.
override func viewDidAppear(animated: Bool) {
// Do any additional setup after loading the view.
let navigationBar = UINavigationBar(frame: CGRectMake(0, 20, self.view.frame.size.width, 44))
// change color of nav bar
let lightTeal = UIColor(red:0.6, green:0.78, blue:0.74, alpha:1.0)
navigationBar.barTintColor = lightTeal
navigationBar.translucent = true
navigationBar.delegate = self
let navigationItem = UINavigationItem()
navigationItem.title = "shOUT"
// left button
let leftButton = UIBarButtonItem(title: "Info", style: UIBarButtonItemStyle.Done, target: self, action: "openInfo")
let info = UIImage(named: "info")
leftButton.image = info
navigationItem.leftBarButtonItem = leftButton
// right button
let rightButton = UIBarButtonItem(title: "Pencil", style: UIBarButtonItemStyle.Done, target: self, action: "openWrite")
let pencil = UIImage(named: "pencil")
rightButton.image = pencil
navigationItem.rightBarButtonItem = rightButton
navigationBar.barStyle = UIBarStyle.Black
navigationBar.items = [navigationItem]
self.view.addSubview(navigationBar)
}
I suggest you to embed a NavigationController inside the TabBarController. Specifically, you should insert one NavigationController for each tab that you have in your TabBarController.
In this way your NavigationBar will always be visible during your navigation inside the tabs and the TabBar as well.
Here is an image of how your storyboard should look like:
Cheers!
I feel like I'm completely overlooking something, since this is so basic.
In a completely bare bones setup:
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.backgroundColor = UIColor.whiteColor()
let rootController = MainViewController()
rootNavigationController = UINavigationController(rootViewController: rootController)
window.rootViewController = rootNavigationController;
window.makeKeyAndVisible()
// Appearance
UINavigationBar.appearance().barTintColor = UIColor.DailyRate.blueColor
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
UINavigationBar.appearance().opaque = false
I get a navigation bar that does not extend behind the status, which should be default behavior.
I just tried and I got proper result. Please find my complete code. I can not find few things in your code(I don't get what you mean by DailyRate) , remaining things are same as your code.
var window: UIWindow?
var rootNavigationController : UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window!.backgroundColor = UIColor.whiteColor()
let rootController = ViewController()
rootNavigationController = UINavigationController(rootViewController: rootController)
window!.rootViewController = rootNavigationController;
window!.makeKeyAndVisible()
// Appearance
UINavigationBar.appearance().barTintColor = UIColor.blueColor()
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
UINavigationBar.appearance().opaque = false
// Override point for customization after application launch.
return true
}
And the result is in following attachment.
I encountered this problem because I was removing the built-in line border at the bottom of the navigation bar, like this:
if let navigationBar = self.navigationController?.navigationBar {
navigationBar.shadowImage = UIImage()
navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
navigationBar.backgroundColor = UIColor.redColor()
}
I was doing the above code inside my view controller's viewWillAppear because some of my VCs have other colors for the navigation bar and I don't want to modify the universal appearance.
The solution was to just create a 1 pt x 1 pt image with the color I want and use it instead of a new empty UIImage instance, like this:
if let navigationBar = self.navigationController?.navigationBar {
let colorImage = UIImage.imageWithColor(self.category.color)
navigationBar.shadowImage = colorImage
navigationBar.setBackgroundImage(colorImage, forBarMetrics: .Default)
navigationBar.tintColor = UIColor.whiteColor()
}
imageWithColor is a function I defined in an extension to UIImage:
class func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRectMake(0, 0, 1, 1)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
It turned out that it was a timing issue.
The root hierarchy was actually set up in the initializer of a separate class called UIManager. However, this class was initialized at the same time as the AppDelegate
var uiManager = UIManager()
and not in application(_, didFinishLaunchingWithOptions _) method, thus creating this weird scenario.
So all I did was
var uiManager: UIManager?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
uiManager = UIManager()
}
And now everything is back to normal.
Thanks to #govindarao-kondala for planting the right idea in my head!