SwiftUI导航栏高度

9

如何获取当前NavigationBar的高度?在UIKit中我们可以使用以下代码来获取:

navigationController?.navigationBar.frame.height

但是对于SwiftUI找不到任何内容...


1
方法可以与在SwiftUI中以编程方式检测Tab Bar或TabView高度中的TabBar相同。 - Asperi
谢谢,这就是答案。 - yoprst
3个回答

23

基于此帖子(感谢Asperi):https://dev59.com/Srjoa4cB1Zd3GeqPHfAi#59972635

struct NavBarAccessor: UIViewControllerRepresentable {
    var callback: (UINavigationBar) -> Void
    private let proxyController = ViewController()

    func makeUIViewController(context: UIViewControllerRepresentableContext<NavBarAccessor>) ->
                              UIViewController {
        proxyController.callback = callback
        return proxyController
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavBarAccessor>) {
    }

    typealias UIViewControllerType = UIViewController

    private class ViewController: UIViewController {
        var callback: (UINavigationBar) -> Void = { _ in }

        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            if let navBar = self.navigationController {
                self.callback(navBar.navigationBar)
            }
        }
    }
}

然后我们可以从任何视图中调用它:

.background(NavBarAccessor { navBar in
      print(">> NavBar height: \(navBar.bounds.height)")
                // !! use as needed, in calculations, @State, etc.
 })

这个很好用。但是不要在NavigationView上使用它,因为导航控制器会为空。此外,在NavBarAccessor中的'typealias'可以被删除。 - José

2

在 @yoprst 的回答基础上,你可以直接返回一个 View 插入到层次结构中,而不是配置计算和 @State 变量:

struct NavigationBarAccessor: UIViewControllerRepresentable {
    var callback: (UINavigationBar) -> (AnyView)
    private let proxyViewController = ProxyViewController()

    func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationBarAccessor>) -> UIViewController {
        self.proxyViewController.callback = callback
        return proxyViewController
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationBarAccessor>) {
    }

    private class ProxyViewController: UIViewController {
        var callback: ((UINavigationBar) -> AnyView)?

        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            if let navigationBar = self.navigationController?.navigationBar {
                _ = self.callback?(navigationBar)
            }
        }
    }
}

使用方法:

VStack {
    NavigationBarAccessor { navigationBar in
        Spacer()
            .frame(height: navigationBar.frame.height)
    }
}

一个通用的约束条件比使用 AnyView 更可取。 - Sega-Zero

-4
使用GeometryReader,像这样:
ZStack {
    GeometryReader { geometry in
        Rectangle().fill(Color.blue).frame(height: geometry.safeAreaInsets.bottom + 44.0)
    }
    Text("Content")
}
.edgesIgnoringSafeArea(.top)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接