Search code examples
iosswiftxcoderesponsive-designuinavigationbar

Base view UI nav bar responsiveness to orientation


I'm super new to iOS app development using Swift and Xcode. Right now, I'm trying to create a base view with a navbar for all my views instead of using a nav controller. When I started in landscape mode, the navbar looks fine, but the height looks off when I switch to portrait mode. When I start in portrait mode, landscape mode looks off where the nav bar is only half of the full length. It seems that when I change to landscape mode, no nav bar is being drawn and it used the old one... In the code below, I have an orientation listener which draws the navbar again, but it doesn't seem to work.

import UIKit

class BaseViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(BaseViewController.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
    }

    deinit {
       NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
    }

    @objc func rotated() {
        if UIDevice.current.orientation.isLandscape {
            print("Landscape")
            createNavBarLandscape()
        } else {
            print("Portrait")
            createNavBarPortrait()
        }
    }
    
    func createNavBarLandscape() {
        let navBar = UINavigationBar(frame: CGRect(x: 0, y: 50, width: view.frame.size.width * 2, height: 24))
        view.addSubview(navBar)
        
        navBar.barTintColor = .white
        let navItem = UINavigationItem(title: "logo")
        let logo = UIImage(named: "logo.png")
        let imageView = UIImageView(image:logo)
        navItem.titleView = imageView
        navBar.setItems([navItem], animated: false)
    }
    
    func createNavBarPortrait() {
        let navBar = UINavigationBar(frame: CGRect(x: 0, y: 50, width: view.frame.size.width, height: 44))
        view.addSubview(navBar)
        
        navBar.barTintColor = .white
        let navItem = UINavigationItem(title: "logo")
        let logo = UIImage(named: "logo.png")
        let imageView = UIImageView(image:logo)
        navItem.titleView = imageView
        navBar.setItems([navItem], animated: false)
    }
}

Starting in portrait mode:
Portrait mode: portrait mode

Landscape mode: landscape mode

Starting in landscape mode:
Landscape mode: landscape mode 2

Portrait mode: portrait mode 2


Solution

  • Give this a try...

    class MyBaseViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            let navBar = UINavigationBar()
            view.addSubview(navBar)
            
            navBar.barTintColor = .white
            let navItem = UINavigationItem(title: "logo")
            let imageView = UIImageView()
            if let logo = UIImage(named: "logo") {
                imageView.image = logo
            }
            navItem.titleView = imageView
            navBar.setItems([navItem], animated: false)
    
            navBar.translatesAutoresizingMaskIntoConstraints = false
            
            // respect safe area
            let g = view.safeAreaLayoutGuide
            
            NSLayoutConstraint.activate([
                navBar.topAnchor.constraint(equalTo: g.topAnchor),
                navBar.leadingAnchor.constraint(equalTo: g.leadingAnchor),
                navBar.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            ])
            
        }
    
    }