简体   繁体   中英

SwiftUI: unexpected behavior with two List side by side and a NavigationView

I have a screen with two List side by side, inside a NavigationView . The layout is rendered correctly, and I can independently scroll both lists. The problem is that, when I scroll the first list, it goes behind the navigation bar without triggering the effect of applying a background color to it. Here's a gif showing what's going on:

在此处输入图像描述

And this is the code I'm using for this view:

struct ContentView: View {

    var body: some View {
        NavigationView {
            HStack(spacing: 0) {
                List {
                    Section(header: Text("Header left")) {
                        ForEach(0..<600) { integer in
                            Text("\(integer)")
                        }
                    }
                }
                .listStyle(InsetGroupedListStyle())
                .frame(minWidth: 0, maxWidth: .infinity)

                List {
                    Section(header: Text("Header right")) {
                        ForEach(0..<400) { integer in
                            Text("\(integer)")
                        }
                    }
                }
                .listStyle(InsetGroupedListStyle())
                .frame(minWidth: 0, maxWidth: .infinity)
            }
            .navigationTitle("Example")
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }

}

Would this be a SwiftUI bug? If not, how can I make the first list correctly interact with the navigation bar when scrolling?

I've ended up with disabling UINavigationBar 's large title and transparency.

import Introspect

@State private var navigationBar: UINavigationBar?

HStack(spacing: 0) {
    ...
}
.navigationBarTitleDisplayMode(.inline)
.introspectNavigationController {
    $0.navigationBar.scrollEdgeAppearance = $0.navigationBar.standardAppearance
    navigationBar = $0.navigationBar
}
.onDisappear {
    navigationBar?.scrollEdgeAppearance = nil
    navigationBar = nil
}

To access UINavigationController I used SwiftUI Introspect lib

It's a bug. The way the NavigationView and NavigationStack work, they only consider the last occurring List or ScrollView in its content to animate the navigation bar.

The only workarounds I can think of now are to:

  1. Hide the navigation bar with .navigationBarHidden(true) or .toolbar(.hidden) (for iOS 16+) modifiers
  2. Fix the navigation bar in place
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(Color.white, for: .navigationBar)
.toolbarBackground(.visible, for: .navigationBar)

for iOS 16+ or the UIKit-ish way for older iOS versions by playing with UINavigationBarAppearance

  1. Implement your own navigation bar, track the lists with geometry readers, and do the animation based on the list positions but the effort here will not be worth it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM