Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ScrollView affects navbar color when scrolling started

Tags:

ios

swift

swiftui

The view below is pushed on NavigationStack. My main point is to have a top bar view, with a background expanding under nav bar, the top bar should have a shadow below, and below is a ScrollView with some content.

struct ContentView: View {

var body: some View {
    VStack (spacing: 0) {
        HStack {
            Text("Title")
        }
        .frame(maxWidth: .infinity)
        .padding()
        .background(.red)
        .compositingGroup()
        .shadow(color: .black, radius: 5)
        .zIndex(1)
        
        ScrollView {
            VStack(spacing: 0) {
                ForEach((1...100), id: \.self) {
                        Text("\($0)…")
                        .frame(maxWidth: .infinity)
                        .background(.white)
                    }
            }
        }
    }
}
}

To make the shadow, applied to title view, visible, I had to change the view zIndex to 1, so that the shadow is drawn above scroll view content. It works fine, but have a very weird side effect. With this code, when the scroll view starts scrolling, the color of the nav bar changes, see below.

If I don't change the zIndex of the title bar, there is no effect like this, but the shadow is not visible.

demo

like image 794
Wujo Avatar asked Nov 02 '25 19:11

Wujo


1 Answers

I was able to reproduce this problem when the view is shown as a child view of a NavigationStack.

The red is extending to the top of the screen because it is in contact with the safe area and the .background modifier that you are using ignores safe areas by default - see background(_:ignoresSafeAreaEdges:). However, the navigation bar is still being shown over your red background, which is why the Back button is also visible.

When the content is scrolled up behind the navigation bar, the background of the navigation bar changes to a Material effect, so you see the lighter color. As you pointed out, this seems to be exceptional behavior due to setting zIndex on the content in that part of the screen.

Here are two ways to prevent it happening:

1. Hide the background behind the navigation bar

This is done by applying .toolbarBackground(.hidden, for: .navigationBar) to the VStack:

var body: some View {
    NavigationStack {
        NavigationLink("show child") {
            VStack(spacing: 0) {
                // content as in your example
            }
            .toolbarBackground(.hidden, for: .navigationBar) // <- ADDED
        }
    }
}

2. Fill the base layer

The problem doesn't happen if you use a ZStack and fill the base layer (the layer below the header and the scrolled content):

var body: some View {
    NavigationStack {
        NavigationLink("show list") {
            ZStack {
                Color.red
                VStack(spacing: 0) {
                    // content as in your example
                }
            }
        }
    }
}
like image 67
Benzy Neez Avatar answered Nov 04 '25 10:11

Benzy Neez



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!