Swift Custom Navigation Controller Class

Alex picture Alex · Feb 18, 2017 · Viewed 19.7k times · Source

Everyone who reads it, hello and thank you. I am writing an application like Viber or WhatsApp for iOS devices using Xcode 8.2.1 and Swift 3.0. I have a problem: I want my app has a navigation controller but not a simple one, I want it to be a custom one. There is a print screen from WhatsApp to be understanding, what I am trying to achieve:

Screenshot of WhatsApp chat with somebody

As we can see, this navigation controller has 3 buttons, label and image with avatar. I also want to change my color to green one. Due to do this I have created class:

import UIKit

class CustomNavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationBar.barTintColor = UIColor.green


        let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 39, height: 39))
        imageView.contentMode = .scaleAspectFit
        let image = UIImage(named: "logo")
        imageView.image = image
        navigationItem.titleView = imageView


    }
}

And it gives this result: enter image description here As you can see it is without picture. I know that if I add this code:

        let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 39, height: 39))
        imageView.contentMode = .scaleAspectFit
        let image = UIImage(named: "logo")
        imageView.image = image
        navigationItem.titleView = imageView

to ViewController, image with logo will appear but I want complete class which I will connect somewhere (for example, in Interface Builder) and it will make a beautiful Navigation Controller with buttons, images and etc. Moreover, I can create a different class with another Navigation Controller and connect it to different screens, on which, for example, I will not need images, only buttons. So question is: how to make custom Navigation Controller class?

I will be really glad and thankful for any help, Thank You!

Answer

Alex picture Alex · Aug 24, 2018

Now, I know the answer! It will be written for Swift 4.1.2. Each class inherited from UIViewController has a property self.navigationController?.navigationBar or navigationItem. You can create you own class like this:

class CustomNavigationController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let color = UIColor(red: 81 / 255, green: 155 / 255, blue: 22 / 255, alpha: 1.0)
        self.navigationController?.navigationBar.barTintColor = color

        let image = UIImage(named: "logo")
        let imageView = UIImageView(image: image)
        imageView.contentMode = .scaleAspectFit
        navigationItem.titleView = imageView
    }

    private func imageView(imageName: String) -> UIImageView {
        let logo = UIImage(named: imageName)
        let logoImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
        logoImageView.contentMode = .scaleAspectFit
        logoImageView.image = logo
        logoImageView.widthAnchor.constraint(equalToConstant: 35).isActive = true
        logoImageView.heightAnchor.constraint(equalToConstant: 35).isActive = true
        return logoImageView
    }

    func barImageView(imageName: String) -> UIBarButtonItem {
        return UIBarButtonItem(customView: imageView(imageName: imageName))
    }

    func barButton(imageName: String, selector: Selector) -> UIBarButtonItem {
        let button = UIButton(type: .custom)
        button.setImage(UIImage(named: imageName), for: .normal)
        button.frame = CGRect(x: 0, y: 0, width: 35, height: 35)
        button.widthAnchor.constraint(equalToConstant: 35).isActive = true
        button.heightAnchor.constraint(equalToConstant: 35).isActive = true
        button.addTarget(self, action: selector, for: .touchUpInside)
        return UIBarButtonItem(customView: button)
    }

}

Now you can inherit any of you UIViewControllers from this class CustomNavigationController and add ass much buttons, icons, change colors, logos and etc. as much as you want (of course, in normal range)! Like this:

class ViewController: CustomNavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.leftBarButtonItem = barImageView(imageName: "picture1")

        let firstImage = barImageView(imageName: "picture2")
        let secondButton = barButton(imageName: "picture3", selector: #selector(secondButtonPressed))

        navigationItem.rightBarButtonItems = [firstImage, secondButton]
    }

    @objc func secondButtonPressed() {
        print("Pressed")
    }

}

This is my solution, maybe not the best, but 100% works! Thank you!