Categories
iOS Development

Customizing your app’s navigation bar titles buttons and background

The default navigation bar you get when implementing a UINavigationController does it’s job but often you want to customize it because it just does not look so fancy.

To customize the background of your UINavigationBar you set its backgroundImage property which means you have to provide a UIImage even if you want to give it a single color.

I created an extension for UIImage that makes it easy to create instances of UIImage on the fly.

extension UIImage {
/// This function creates a 1x1 pt colored image
  static func withColor(color: UIColor) -> UIImage {
    let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
    UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
    color.setFill()
    UIRectFill(rect)
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
    UIGraphicsEndImageContext()
    return image
  }
}Code language: JavaScript (javascript)

Now we can use this extension to create a background and use it as a background image for our navigation bar:

/// Declare a white with 0.8 alpha
let background = UIImage.withColor(color: UIColor.white.withAlphaComponent(0.8))

/// Set the color as background 
navigationController?.navigationBar.setBackgroundImage(background, for: .default)
navigationController?.navigationBar.setBackgroundImage(background, for: .compact)Code language: JavaScript (javascript)

If you want to make your navigation bar’s background invisible you can just set it to an empty UIImage:

navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .compact)Code language: CSS (css)

The shadow of the navigation bar is an image as well. Often you want to make it invisible. You achieve this by setting the shadowImage property:

navigationController?.navigationBar.shadowImage = UIImage()Code language: Swift (swift)

If we want to set custom fonts for our navigation bar we cannot do this directly as we would do it when customizing some UILabel. Instead we do this by setting the navigation bar’s titleTextAttributes and largeTitleTextAttributes properties:

/// Setting the font for the centered title
navigationController?.navigationBar.titleTextAttributes = [ NSAttributedString.Key.font: UIFont(named: "someFont")]

/// Setting the font for largeTitles, if enabled via:
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.largeTitleTextAttributes = [ NSAttributedString.Key.font: UIFont(named: "someFont")]Code language: JavaScript (javascript)

One is still missing, which is the font on the navigation bar’s buttons. I could not manage to set this from within a view controller, for me it was only possible from the AppDelegate. You use the appearance proxy for that which changes the appearance of instances of UIBarButtonItem for the whole app. Just add the following to your AppDelegate.application(_:didFinishLaunchingWithOptions:):

UIBarButtonItem.appearance().setTitleTextAttributes(
[NSAttributedString.Key.font: UIFont(named: "someFont")],
                              for: .normal)Code language: CSS (css)

Leave a Reply

Your email address will not be published. Required fields are marked *