Maray97
Maray97

Reputation: 172

Set UINavigationBar height proportionally to screen size

I have 5 tabs in UITabBarController and each of them is embedded in a UINavigationController. I would like to set the height of this tab to 8% of the screen, but I cannot set constraints to StoryBoard, also if I try to set it from code it turns black and break UI controls. The code for my UINavigationController is this:


class NavBarController: UINavigationController {
    override func viewDidLayoutSubviews() {
        self.navigationBar.topItem?.titleView = UIImageView(image: UIImage(named: "image"))
        self.navigationBar.topItem?.titleView?.contentMode = .scaleAspectFit
        let gradient = CAGradientLayer()
        var bounds = self.navigationBar.bounds
        bounds.size.height += self.view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
        bounds.origin.y -= self.view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
        gradient.frame = bounds
        gradient.colors = [UIColor.black, UIColor.white]
        gradient.locations = [0.0, 1.0]
        self.navigationBar.setBackgroundImage(image(fromLayer: gradient), for: .default)
    }
    
    func image(fromLayer layer: CALayer) -> UIImage {
        UIGraphicsBeginImageContext(layer.frame.size)
        layer.render(in: UIGraphicsGetCurrentContext()!)
        let outputImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return outputImage!
    }
}

I tried by setting:

self.navigationBar.frame.size.height = (self.view.superview?.frame.height)! * 0.08
self.navigationBar.layoutIfNeeded()

at the beginning of viewDidLayoutSubviews, but it does not work and also breaks the gradient background. Can someone help me? The ideal solution would be through storyboard, but I cannot simply set the UINavigationItem height constraint to its view height.

Upvotes: 0

Views: 86

Answers (1)

user1922718
user1922718

Reputation: 147

After spending some time looking into this, I found that UINavigationBar is given a height of 44pts several times throughout the transition process. Since UIKit is insisting on a height of 44, I decided to employ some trickery with a custom setter.

class NavigationBar: UINavigationBar {
    private var _frame: CGRect!
    override var frame: CGRect {
        set {
            _frame = CGRect(origin: newValue.origin, size: CGSize(width: newValue.width, height: 22))
        }
        get {
            _frame
        }
    }
}

Here I'm forcing the height of the navigation bar to 22 pts. However, after compiling and running the nav bar is still 44. Why? Because UIKit is also setting a constraint, forcing the height to 44. This means that AutoLayout is reverting the height to 44 upon layout. Seems that this is something Apple really doesn't want you to change. enter image description here

Upvotes: 1

Related Questions