Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save iNono22/a5391c29fe1d5d4c5171337a931032df to your computer and use it in GitHub Desktop.
Save iNono22/a5391c29fe1d5d4c5171337a931032df to your computer and use it in GitHub Desktop.
Colourable UINavigationController that supports different colors for navigation bars among different view controllers

Overview

ColorableNavigationController is tiny subclass of UINavigationController that supports different colors for navigation bars among different view controllers.

Code snippet was created to answer on my question at Stackoverflow.

How to install

Just add code from ColorableNavigationController.swift or copy that file to your project.

Usage

  1. Use ColorableNavigationController as your root UINavigationController (you can init it by yourself or change in Storyboard).
  2. Adopt needed child view controllers to NavigationBarColorable protocol:

Colors will be set automatically on push or pop actions. Please don't forget to set initial values of barTintColor and tintColor on first load of UINavigationController.

Protocol

public protocol NavigationBarColorable: class {
	var navigationTintColor: UIColor? { get } // optional
	var navigationBarTintColor: UIColor? { get }
}

Example

class ViewControllerA: UIViewController, NavigationBarColorable {
	public var navigationBarTintColor: UIColor? { return UIColor.blue }

	override func viewDidLoad() {
		super.viewDidLoad()

		navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Push", style: .plain, target: self, action: #selector(self.showController))
	}

	func showController() {
		navigationController?.pushViewController(ViewControllerB(), animated: true)
	}
}

class ViewControllerB: UIViewController, NavigationBarColorable {
	public var navigationBarTintColor: UIColor? { return UIColor.red }
}

let navigationController = ColorableNavigationController(rootViewController: ViewControllerA())
//
// ColorableNavigationController.swift
//
// Created by Vasily Ulianov on 26.10.16.
//
import UIKit
/// Navigation bar colors for `ColorableNavigationController`, called on `push` & `pop` actions
public protocol NavigationBarColorable: class {
var navigationTintColor: UIColor? { get }
var navigationBarTintColor: UIColor? { get }
}
public extension NavigationBarColorable {
var navigationTintColor: UIColor? { return nil }
}
/**
UINavigationController with different colors support of UINavigationBar.
To use it please adopt needed child view controllers to protocol `NavigationBarColorable`.
- note: Don't forget to set initial tint and barTint colors
*/
open class ColorableNavigationController: UINavigationController {
private var previousViewController: UIViewController? {
guard viewControllers.count > 1 else {
return nil
}
return viewControllers[viewControllers.count - 2]
}
override open func pushViewController(_ viewController: UIViewController, animated: Bool) {
if let colors = viewController as? NavigationBarColorable {
self.setNavigationBarColors(colors)
}
super.pushViewController(viewController, animated: animated)
}
override open func popViewController(animated: Bool) -> UIViewController? {
if let colors = self.previousViewController as? NavigationBarColorable {
self.setNavigationBarColors(colors)
}
// Let's start pop action or we can't get transitionCoordinator()
let popViewController = super.popViewController(animated: animated)
// Secure situation if user cancelled transition
transitionCoordinator?.animate(alongsideTransition: nil, completion: { [weak self] (context) in
guard let colors = self?.topViewController as? NavigationBarColorable else { return }
self?.setNavigationBarColors(colors)
})
return popViewController
}
private func setNavigationBarColors(_ colors: NavigationBarColorable) {
if let tintColor = colors.navigationTintColor {
self.navigationBar.tintColor = tintColor
}
self.navigationBar.barTintColor = colors.navigationBarTintColor
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment