将 UINavigationBar 高度设置为与屏幕大小成比例

Set UINavigationBar height proportionally to screen size

我在 UITabBarController 中有 5 个选项卡,每个选项卡都嵌入在 UINavigationController 中。我想将此选项卡的高度设置为屏幕的 8%,但我无法为 StoryBoard 设置约束,而且如果我尝试从代码中设置它,它会变成黑色并破坏 UI 控件。 我的 UINavigationController 的代码是这样的:


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!
    }
}

我试过设置:

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

在 viewDidLayoutSubviews 的开头,但它不起作用并且还破坏了渐变背景。有人能帮我吗?理想的解决方案是通过故事板,但我不能简单地将 UINavigationItem 高度约束设置为其视图高度。

经过一番研究,我发现在整个过渡过程中,UINavigationBar 多次被赋予 44pts 的高度。由于 UIKit 坚持 44 的高度,我决定使用一些技巧来自定义 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
        }
    }
}

这里我将导航栏的高度强制设置为 22 磅。但是,编译后 运行 导航栏仍然是 44。为什么?因为 UIKit 还设置了一个约束,强制高度为 44。这意味着 AutoLayout 在布局时将高度恢复为 44。看来这是 Apple 真的不想让你改变的东西。