获取大标题导航栏的默认收缩高度和展开高度
Get the default shrunk and expanded height of large title navigation bar
我为导航栏启用了大标题:
navigationController?.navigationBar.prefersLargeTitles = true
这使得导航栏以展开的高度开始,并随着用户向下滚动而缩小。
现在,我想在导航栏内添加一个子视图,它会根据导航栏的高度调整大小。为此,我需要获得 导航栏的最大高度和最小高度,这样我就可以计算出它扩展了多少。
我可以这样获取当前导航栏的高度:
guard let height = navigationController?.navigationBar.frame.height else { return }
print("Navigation height: \(height)")
我在 scrollViewDidScroll
里面调用这个,当我滚动时,似乎展开高度在 96 左右,收缩高度在 44 左右。但是,我不想硬编码值。
iPhone 12
Expanded (96.33)
Shrunk (44)
iPhone 8
Expanded (96.5)
Shrunk (44)
我也只能在用户实际上下滚动时获取这些值,这在生产环境中不起作用。即使我强迫用户滚动,也为时已晚,因为我需要提前知道两个高度,这样我就可以插入调整大小的子视图。
I want to get these values, but without hardcoding or scrolling
有什么方法可以同时获得缩小和展开的导航栏的高度?
使用以下扩展你可以获得额外的高度
extension UINavigationBar
{
var largeTitleHeight: CGFloat {
let maxSize = self.subviews
.filter { [=10=].frame.origin.y > 0 }
.max { [=10=].frame.origin.y < .frame.origin.y }
.map { [=10=].frame.size }
return maxSize?.height ?? 0
}
}
我之前说了你可以通过关注
来增加身高
guard let height = navigationController?.navigationBar.frame.maxY else { return }
print("Navigation height: \(height)")
let window = UIApplication.shared.keyWindow
let topPadding = window?.safeAreaInsets.top
let extendedHeight = height - topPadding
您可以通过从扩展高度中减去差异来缩小高度
guard let difference = navigationController?.navigationBar.lagreTitleHeight else {return}
let shrunkHeight = extendedHeight - difference
一年后遇到了我自己的问题。另一个答案没有用,所以我使用了视图层次结构。
缩小的样子好像是嵌入了一个叫_UINavigationBarContentView
的class。由于这是私有 class,我无法直接访问它。但是,它的 y
起源是 0
并且里面有一个 UILabel
。这就是我需要知道的!
extension UINavigationBar {
func getCompactHeight() -> CGFloat {
/// Loop through the navigation bar's subviews.
for subview in subviews {
/// Check if the subview is pinned to the top (compact bar) and contains a title label
if subview.frame.origin.y == 0 && subview.subviews.contains(where: { [=10=] is UILabel }) {
return subview.bounds.height
}
}
return 0
}
}
用法:
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Navigation"
if
let navigationBar = navigationController?.navigationBar,
let window = UIApplication.shared.keyWindow
{
navigationBar.prefersLargeTitles = true /// Enable large titles.
let compactHeight = navigationBar.getCompactHeight() // 44 on iPhone 11
let statusBarHeight = window.safeAreaInsets.top // 44 on iPhone 11
let navigationBarHeight = compactHeight + statusBarHeight
print(navigationBarHeight) // Result: 88.0
}
}
这个答案的缺点是,如果 Apple 更改了 UINavigationBar
的内部结构,它可能无法工作。不过对我来说已经足够好了。
我为导航栏启用了大标题:
navigationController?.navigationBar.prefersLargeTitles = true
这使得导航栏以展开的高度开始,并随着用户向下滚动而缩小。
现在,我想在导航栏内添加一个子视图,它会根据导航栏的高度调整大小。为此,我需要获得 导航栏的最大高度和最小高度,这样我就可以计算出它扩展了多少。
我可以这样获取当前导航栏的高度:
guard let height = navigationController?.navigationBar.frame.height else { return }
print("Navigation height: \(height)")
我在 scrollViewDidScroll
里面调用这个,当我滚动时,似乎展开高度在 96 左右,收缩高度在 44 左右。但是,我不想硬编码值。
iPhone 12
Expanded (96.33) | Shrunk (44) |
---|---|
iPhone 8
Expanded (96.5) | Shrunk (44) |
---|---|
我也只能在用户实际上下滚动时获取这些值,这在生产环境中不起作用。即使我强迫用户滚动,也为时已晚,因为我需要提前知道两个高度,这样我就可以插入调整大小的子视图。
I want to get these values, but without hardcoding or scrolling |
---|
有什么方法可以同时获得缩小和展开的导航栏的高度?
使用以下扩展你可以获得额外的高度
extension UINavigationBar
{
var largeTitleHeight: CGFloat {
let maxSize = self.subviews
.filter { [=10=].frame.origin.y > 0 }
.max { [=10=].frame.origin.y < .frame.origin.y }
.map { [=10=].frame.size }
return maxSize?.height ?? 0
}
}
我之前说了你可以通过关注
来增加身高guard let height = navigationController?.navigationBar.frame.maxY else { return }
print("Navigation height: \(height)")
let window = UIApplication.shared.keyWindow
let topPadding = window?.safeAreaInsets.top
let extendedHeight = height - topPadding
您可以通过从扩展高度中减去差异来缩小高度
guard let difference = navigationController?.navigationBar.lagreTitleHeight else {return}
let shrunkHeight = extendedHeight - difference
一年后遇到了我自己的问题。另一个答案没有用,所以我使用了视图层次结构。
缩小的样子好像是嵌入了一个叫_UINavigationBarContentView
的class。由于这是私有 class,我无法直接访问它。但是,它的 y
起源是 0
并且里面有一个 UILabel
。这就是我需要知道的!
extension UINavigationBar {
func getCompactHeight() -> CGFloat {
/// Loop through the navigation bar's subviews.
for subview in subviews {
/// Check if the subview is pinned to the top (compact bar) and contains a title label
if subview.frame.origin.y == 0 && subview.subviews.contains(where: { [=10=] is UILabel }) {
return subview.bounds.height
}
}
return 0
}
}
用法:
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Navigation"
if
let navigationBar = navigationController?.navigationBar,
let window = UIApplication.shared.keyWindow
{
navigationBar.prefersLargeTitles = true /// Enable large titles.
let compactHeight = navigationBar.getCompactHeight() // 44 on iPhone 11
let statusBarHeight = window.safeAreaInsets.top // 44 on iPhone 11
let navigationBarHeight = compactHeight + statusBarHeight
print(navigationBarHeight) // Result: 88.0
}
}
这个答案的缺点是,如果 Apple 更改了 UINavigationBar
的内部结构,它可能无法工作。不过对我来说已经足够好了。