Change UINavigationController color and font - ios

I'm writing my app router like this:
final class AppRouter {
let navigationController: UINavigationController
init(window: UIWindow) {
navigationController = UINavigationController()
window.rootViewController = navigationController
...
}
I'm calling router initialiser in application:didFinishLaunchingWithOptions: method.
I was trying to change it style (colour, font and other) by changing it properties, child properties, using UINavigationBar.appearance()
Nothing works. I was setting translucent to false. Only storyboard changes are making any effect, but then I have storyboard based navigation, that I don't want to have.
I have seen many posts about this issue, nothing is working.
If someone have cookbook, that is working on newest iOS (currently 11.4), please share!
Edit:
Like I said making changes like:
UINavigationBar.appearance().barTintColor = color
UINavigationBar.appearance().isTranslucent = false
this is used in didFinishLaunching.
or in constructor:
navigationController.navigationBar.barTintColor = color
Both methods fail to set color of navigation controller bar.
Edit 2:
App delegate calls:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
self.window = window
window.makeKeyAndVisible()
appRouter = AppRouter(window: window)
return true
}

Use below extension for UINavigationController
extension UINavigationController
{
func setMainTopNavigationBarAttribute() -> Void
{
self.navigationBar.shadowImage = UIImage()
self.navigationBar.isTranslucent = false
self.navigationBar.barTintColor = UIColor.black
self.navigationBar.tintColor = UIColor.white
self.navigationBar.backgroundColor = UIColor.clear
let navBarAttributesDictionary: [NSAttributedStringKey: Any]? = [
NSAttributedStringKey.foregroundColor: UIColor.black,
NSAttributedStringKey.font: UIFont(name: "HelveticaNeue-Bold", size: 18.0)
]
self.navigationBar.titleTextAttributes = navBarAttributesDictionary
}
}
final class AppRouter {
let navigationController: UINavigationController
init(window: UIWindow) {
navigationController = UINavigationController()
window.rootViewController = navigationController
navigationController.setMainTopNavigationBarAttribute()
}

Related

TabBar and NavigationBar do not change colors

I have run into some issues running xcode 14 and ios 16.
The navigation bar does not change colors, and the Tab Bar is the same color as the background (I think it should have a different tint).
class MainTabController: UITabBarController {
// MARK: - Properties
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
configureViewControllers()
}
// MARK: - Helpers
func configureViewControllers() {
let feed = FeedController()
let nav1 = templateNavigationController(image: UIImage(named: "home_unselected"), rootViewController: feed)
let explore = ExploreController()
let nav2 = templateNavigationController(image: UIImage(named: "search_unselected"), rootViewController: explore)
let notifications = NotificationsController()
let nav3 = templateNavigationController(image: UIImage(named: "search_unselected"), rootViewController: notifications)
let conversations = ConversationsController()
let nav4 = templateNavigationController(image: UIImage(named: "search_unselected"), rootViewController: conversations)
viewControllers = [nav1, nav2, nav3, nav4]
}
func templateNavigationController(image: UIImage?, rootViewController: UIViewController) -> UINavigationController {
let nav = UINavigationController(rootViewController: rootViewController)
nav.tabBarItem.image = image
nav.navigationBar.barTintColor = .white
return nav
}
}
I have tried setting the appearance of the navigation bar:
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = .white
nav.navigationBar.standardAppearance = appearance
nav.navigationBar.scrollEdgeAppearance = nav.navigationBar.standardAppearance
this seems a bit redundant, and do you have to do this everytime for each nav controller?
No, you don't have to do this for each Navigation Controller.
You can make an extension of UINavigationBar.
extension UINavigationBar {
static func create() {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithOpaqueBackground()
navBarAppearance.backgroundColor = .white
appearance().standardAppearance = navBarAppearance
appearance().scrollEdgeAppearance = navBarAppearance
appearance().compactAppearance = navBarAppearance
}
}
and call UINavigationBar.create() from your application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
Similar approach can be done for the UITabBar

UICollectionViewController and UIViewController [duplicate]

This question already has answers here:
UICollectionView: must be initialized with a non-nil layout parameter
(7 answers)
Closed 4 years ago.
I am new in Swift. I have 3 UIViewControllers:
MainScreenController
RegistrationFormController
LoginFormController
and 1 UITabBarController
MainTabBarController
and 2 ColletionViewControllers:
VideoController
TopVideoController
When I click on the button on the LoginFormController to open MainTabBarController with either 2 ColletionViewControllers seems an error, the error is mentioned below:
'UICollectionView must be initialized with a non-nil layout parameter'
AppDelegate:
class CustomNavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var navigationController: UINavigationController?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
if let window = window {
let mainVC = MainScreenController()
navigationController = CustomNavigationController(rootViewController: mainVC)
window.rootViewController = navigationController
window.makeKeyAndVisible()
}
UINavigationBar.appearance().isTranslucent = false
UINavigationBar.appearance().tintColor = .white
UINavigationBar.appearance().barTintColor = UIColor.darkBlue
UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
UINavigationBar.appearance().largeTitleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
FirebaseApp.configure()
return true
}
Help me to understand how it works.
From the Apple Documentation, you need to use init(frame: CGRect,
collectionViewLayout layout: UICollectionViewLayout) when initializing your collection view controllers.

iOS 11 custom navigation bar gives two bars

When I try to add a custom UINavigationBar to a view controller like this
class ViewController: UIViewController
{
static let nav_bar_height: CGFloat = 64
let nav_bar: UINavigationBar =
{
let nav_bar = UINavigationBar()
nav_bar.translatesAutoresizingMaskIntoConstraints = false
nav_bar.backgroundColor = .blue
return nav_bar
}()
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = .yellow
view.addSubview(nav_bar)
nav_bar.heightAnchor.constraint(equalToConstant: ViewController.nav_bar_height).isActive = true
nav_bar.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
nav_bar.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
nav_bar.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
}
}
two distinct bars show up.
Any idea on why there is the white colored bar with a smaller height?
This is the AppDelegate
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let vc = ViewController()
window?.rootViewController = vc
// Override point for customization after application launch.
return true
}...
You're probably in navigation interface with a UINavigationController as your view controller's parent.
So the second navigation bar is the UINavigationController's navigation bar.

UINavigationBar does not extend behind status bar

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!

Swift - Programmatically creating Views Issue, unable to find stored property

I am trying to learn Swift and iOS Views and ViewControllers.
var window: UIWindow?
var rootViewController: MyCustomView?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
// Override point for customization after application launch.
self.rootViewController = MyCustomView()
self.rootViewController!.backgroundColor = UIColor.orangeColor()
var rect = CGRectMake(20, 20, 100, 100)
var label = UILabel(frame: rect)
label.text = "Hello iOS Views"
label.backgroundColor = UIColor.orangeColor()
self.window!.rootViewController = self.rootViewController
self.window!.backgroundColor = UIColor.whiteColor()
self.window!.makeKeyAndVisible()
return true
I am getting an error when I compile, "Could not find member 'rootViewController'" on the following line:
self.window!.rootViewController = self.rootViewController
Not sure why Xcode 6 Beta is not liking it but it's able to find this line:
self.rootViewController!.backgroundColor = UIColor.orangeColor()
The problem is that MyCustomView is a UIView. But UIWindow's rootViewController expects a UIViewController.
Generally you have confused yourself right through your code by not distinguishing view controllers from views. But you did name MyCustomView sensibly, which is good. The fact that it has a backgroundColor helps to prove that it is a view, not a view controller (view controllers have no background color).

Resources