Right Way of Positioning an Always Visible Overlay on Top of Navigation Bar That Aligns With Other Navigation Items

Starting with Liquid Glass, the navigation items seem not to be vertically centered within the navigation bar. This makes it very challenging to position an overlay on top of the navigation bar so that it aligns naturally with other elements such as the back button, dismiss button, and others.

We want to achieve this for a progress bar so that it remains visible regardless of which views are pushed underneath. Therefore, we cannot add it as a navigation item on each screen, as doing so would cause the progress bar to animate repeatedly as new screens are pushed onto the stack.

This used to be easier pre liquid glass since navigation items were centered vertically within the navigation bar.

The approach I tried to center the progress bar in the navigation bar:

  • Get access to the top safe area insets through GeometryReader
  • Get access to the the status bar height through UIWindowScene's statusBarManager
  • Subtract status bar height from top safe area inset to calculate the navigation bar height
  • Update the padding of the progress bar accordingly to make sure it is centered within the navigation bar

This works, but as I mentioned, now the navigation items are not centered, and the amount of vertical offset they have seems to differ from one screen to another, making it impossible to come up with an additional padding value to align across devices.

See how the navigation item looks like within the navigation bar in the view debugger (doesn't matter if it is UINavigationController or NavigationStack the behaviour is the same, also please note that the positioning is the same for a view without an explicit leading toolbar item, where the default back button is provided by the system when a view is pushed):

Existing code (without any hacky solutions) to add a progress bar on top as overlay:

struct ContentView: View {

    @State var shouldShowOverlay = false

    var body: some View {
        NavigationStack {
            NavigationLink("Go to View2") { View2() }
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .topBarLeading) {
                        Button {
                        } label: {
                            Image(systemName: "chevron.left")
                        }

                    }
                }
        }

        .overlay(alignment: .top) {
            ProgressView(value: 0.5)
                .frame(width: 200)
            // what to add as padding here
//                .padding(.top, 16.0)

        }
}

How it looks:

Some additional observations for the navigation bar item here:

There seems to be 4 _UINavigationBarPlatterAnimationViews in the view stack, prior to the bar button item:


The first two seems to be fine, they both have (0, 0, 44, 44) for both frame and bounds


The third one’s frame has height and width of 48.2, and x, y values of -2.1.

The last one’s frame has 40,17 for height and width and 1.92 for x,y values. Both views have the following bounds: (0, 0, 44, 44).

I also tried to access to the origin of the back bar button item so that I could calculate where the position the overlay, but that also didn't yield to something useful, not to mention it would also be a super hacky solution.

So my ultimate question is, is there a clean way to position an overlay on top of the navigation bar that vertically aligns with other navigation bar items, or should we just position it elsewhere and do not mess with navigation bar anymore?

Any input would be greatly appreciated.

Right Way of Positioning an Always Visible Overlay on Top of Navigation Bar That Aligns With Other Navigation Items
 
 
Q