如何根据背景图片调整NavigationBar尺寸并解决高度重置问题?
Hey there! Let's fix that tricky NavigationBar height issue you're dealing with. I’ve faced this exact problem before—when you set the height manually, the system’s default constraints often override it, which is why it briefly shows the right size then snaps back. Here’s how to make it stick:
The core issue is that the default UINavigationBar uses system-defined layout rules. By creating a custom subclass, you can take control of its size:
class CustomNavBar: UINavigationBar { override func sizeThatFits(_ size: CGSize) -> CGSize { // Grab your background image to get its natural height guard let bgImage = backgroundImage(for: .default) else { return super.sizeThatFits(size) } // Return a size that matches the screen width and image height return CGSize(width: UIScreen.main.bounds.width, height: bgImage.size.height) } }
Then, in your view controller, replace the default navigation bar with your custom one:
override func viewDidLoad() { super.viewDidLoad() let customBar = CustomNavBar() // Set your background image (make sure it's sized properly for different screen densities!) customBar.setBackgroundImage(UIImage(named: "your-nav-bg"), for: .default) // Turn off large titles if you're using them—they can mess with custom heights customBar.prefersLargeTitles = false customBar.isTranslucent = false // Translucency can cause layout shifts // Assign the custom bar to your navigation controller navigationController?.navigationBar = customBar }
If your title or navigation buttons get cut off after setting the custom height, add this to your CustomNavBar class to recenter them:
override func layoutSubviews() { super.layoutSubviews() guard let bgImage = backgroundImage(for: .default) else { return } // Force the bar's frame to match our desired size frame = CGRect(x: 0, y: frame.origin.y, width: UIScreen.main.bounds.width, height: bgImage.size.height) // Reposition all subviews to be vertically centered for subview in subviews { subview.center.y = frame.height / 2 } }
If your app supports rotation, add this to keep the bar sized correctly when the screen flips:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) invalidateIntrinsicContentSize() }
- Make sure your background image is optimized for different screen sizes (use asset catalogs with 1x/2x/3x variants).
- Double-check that you haven’t enabled
navigationController?.hidesBarsOnScrollor other auto-hide features—these can override custom heights.
Give these steps a shot! Overriding sizeThatFits is usually the magic fix here, since it tells the navigation controller exactly how big the bar should be. Let me know if you hit any snags with subview positioning or orientation!
内容的提问来源于stack exchange,提问作者progNewbie

