Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI NavigationBar height

How to get current NavigationBar height? In UIKit we could get

navigationController?.navigationBar.frame.height

but can't find anything for SwiftUI...

like image 389
yoprst Avatar asked Feb 15 '20 17:02

yoprst


People also ask

How do I get the navigation bar height in Swift?

height; const navbarHeight = screenHeight – windowHeight + StatusBar.

How do I customize my navigation bar in SwiftUI?

To change a navigation bar color in SwiftUI, you apply toolbarBackground modifier to the content view of NavigationStack . NavigationView is deprecated in iOS 16. toolbarBackground accepts two parameters. ShapeStyle : The style to display as the background of the bar.

What is navigation bar height iOS?

On iPhone tab bars remain 49 points tall in portrait and 32 points tall in landscape. iPhone X added extra height for the Home Bar to toolbars and tab bars and their sizes are unchanged from iOS 11: 83 points tall in portrait and 53 points tall in landscape.


2 Answers

Based on this post (thanks to Asperi): https://stackoverflow.com/a/59972635/12299030

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

And then we can call this from any View:

.background(NavBarAccessor { navBar in
      print(">> NavBar height: \(navBar.bounds.height)")
                // !! use as needed, in calculations, @State, etc.
 })
like image 187
yoprst Avatar answered Sep 21 '22 13:09

yoprst


Building on @yoprst 's response, rather than configure calculations and @State variables, you could also return a View to insert directly into the hierarchy:

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

Usage:

VStack {
    NavigationBarAccessor { navigationBar in
        Spacer()
            .frame(height: navigationBar.frame.height)
    }
}
like image 37
rob_the_dev Avatar answered Sep 22 '22 13:09

rob_the_dev