将 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 真的不想让你改变的东西。
我在 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 真的不想让你改变的东西。