Custom UINavigationBar does not honour given height

Viewed 89

I have a custom UINavigationBar, called MapNavBar. This class is declared as follows:

class MapNavBar: UINavigationBar {

override func sizeThatFits(_ size: CGSize) -> CGSize {
    let screenSize = UIScreen.main.bounds.size
    let landscape = screenSize.width > screenSize.height
    if landscape {
        let navBarHeight: CGFloat = 44.0
        return CGSize(width: screenSize.width, height: navBarHeight)
    }
    return super.sizeThatFits(size)
}

}

The custom navigation bar is assigned to the navigation controller like so:

navController.setValue(MapNavBar(), forKeyPath : "navigationBar")

Now when the orientation changes to landscape I would like to keep the navigation bar height to the standard (portrait orientation) height of 44. So in the MapController viewWillLayoutSubviews I do:

override func viewWillLayoutSubviews() {

    if let navController = ... {
        let screenSize = UIScreen.main.bounds.size
        let landscape = screenSize.width > screenSize.height
        if landscape {
            let navBarHeight = navController.navigationBar.sizeThatFits(screenSize).height

            // Resize navBar
            navController.navigationBar.frame = CGRect(x: 0, y: 0, width: Int(screenSize.width), height: Int(navBarHeight))
        }
    }
    super.viewWillLayoutSubviews()
}

Despite all efforts, the custom navigation bar height remains at 32 points when in landscape. I have checked and the navigationBar property of the navigation controller is indeed an instance of my custom MapNavBar.

Does anyone know why this happens and how to fix it?

Thanks

1 Answers

Try this:

class MapNavBar: UINavigationBar {

    let navBarHeight: CGFloat = 64 //44 + 20 Where 20 is for status bar, it is hidden in landscape mode always

    override func sizeThatFits(_ size: CGSize) -> CGSize {

        let frame = self.frame
        let screenSize = UIScreen.main.bounds.size
        let landscape = screenSize.width > screenSize.height
        if landscape {
            return CGSize(width: frame.width, height: navBarHeight)
        }
        return super.sizeThatFits(size)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let screenSize = UIScreen.main.bounds.size
        let landscape = screenSize.width > screenSize.height
        if landscape {
            let y = UIApplication.shared.statusBarFrame.height
            frame = CGRect(x: frame.origin.x, y:  y, width: frame.size.width, height: navBarHeight)

            for subview in self.subviews {
                var stringFromClass = NSStringFromClass(subview.classForCoder)
                if stringFromClass.contains("BarBackground") {
                    subview.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: navBarHeight)
                    subview.backgroundColor = self.backgroundColor
                }

                stringFromClass = NSStringFromClass(subview.classForCoder)
                if stringFromClass.contains("BarContent") {
                    subview.frame = CGRect(x: subview.frame.origin.x, y: 0, width: subview.frame.width, height: navBarHeight)
                    subview.backgroundColor = self.backgroundColor
                }
            }
        }
    }
}

enter image description here

Related