17
votes

I can't set a background color under ScrollView in SwiftUI. When I use .background(Color.red) the background is cut off so it doesn't go under navigation bar and scrolling seems to be broken. I tried a couple of solutions but each of them doesn't work. I have a simple view hierarchy

NavigationView {
    ScrollView([.vertical], showsIndicators: true) {
        VStack {
            ForEach(0...50, id: \.self) { _ in
                Text("Text text")
            }
        }
    }
    .navigationBarTitle("Title", displayMode: .large)
}
.navigationViewStyle(StackNavigationViewStyle())

it works as expected

enter image description here

now, I would like to add a background color, I tried the following solutions

1

NavigationView {
    ScrollView([.vertical], showsIndicators: true) {
        VStack {
            ForEach(0...50, id: \.self) { _ in
                Text("Text text")
            }
        }
    }
    .background(Color.red)
    .navigationBarTitle("Title", displayMode: .large)
}
.navigationViewStyle(StackNavigationViewStyle())

result

enter image description here

2

NavigationView {
    ZStack {
        Color.red
        ScrollView([.vertical], showsIndicators: true) {
            VStack {
                ForEach(0...50, id: \.self) { _ in
                    Text("Text text")
                }
            }
        }
        .navigationBarTitle("Title", displayMode: .large)
    }
}
.navigationViewStyle(StackNavigationViewStyle())

result

enter image description here

3

NavigationView {
    ZStack {
        Color.red.edgesIgnoringSafeArea([.all])
        ScrollView([.vertical], showsIndicators: true) {
            VStack {
                ForEach(0...50, id: \.self) { _ in
                    Text("Text text")
                }
            }
        }
        .navigationBarTitle("Title", displayMode: .large)
    }
}
.navigationViewStyle(StackNavigationViewStyle())

result

enter image description here

How to set up a background color under ScrollView packed in NavigationView?

// edit:

The animation below presents a desirable effect (it is made with UIKit).

enter image description here

4
I have also the same issue. Seems like another SwiftUI Bug.Apostolos
Even if I put the scrollView into a ZStack { Color.red, ScrollView } I have the same problem.Apostolos
Did u find any solution to this?arata
Unfortunately, no. I had abandoned SwiftUI and switched to UIKit. SwiftUI is incomplete and can't be used in production...kampro
Still not workingmawus

4 Answers

7
votes

After exhausting all possibilities, I landed with the below solution which works perfectly for what you want to achieve.

struct DemoView: View {
    
    init(){
        let navigationBarAppearance = UINavigationBarAppearance()
        navigationBarAppearance.backgroundColor = UIColor.red
        UIScrollView.appearance().backgroundColor = UIColor.red
    }
    
    var body: some View {

        NavigationView{
                ScrollView{
                    VStack{   
                        ForEach(0..<30, id: \.self){ _ in
                                Text("Text Text").foregroundColor(Color.black)
                        }
                    }.frame(maxWidth: .infinity)
                     .background(Color(UIColor.red))
            
            }.navigationBarTitle("Title")
        }  
    }
}

Hope this helps;)

4
votes

This is a hacky SwiftUI solution:

iOS 13 and iOS 14

NavigationView {
    ScrollView {
        VStack {
            // ...
        }
        .background(Color.red.frame(height: 99999999))
    }
}
2
votes

You can achieve nearly the same behaviour using the code below which uses List View.

struct DemoView: View {
    init(){
        let navigationBarAppearance = UINavigationBarAppearance()
        navigationBarAppearance.backgroundColor = UIColor.red
        UITableView.appearance().separatorStyle = .none
        UITableView.appearance().backgroundColor = UIColor.red
    }
    
    var body: some View {

        NavigationView{
 
                List{

                    ForEach(0..<30, id: \.self){ _ in
                        
                        Text("Text Text")
                        
                    }.listRowBackground(Color(UIColor.red))
            }
            }.navigationBarTitle("Title")
        }
        
    }
}

The code produces these views :1 2

0
votes

You could something like this:

struct ContentView: View {
    init() {
        //Use this if NavigationBarTitle is with Large Font
        UINavigationBar.appearance().backgroundColor = .red
    }
    var body: some View {
        NavigationView {
            ScrollView([.vertical], showsIndicators: true) {
                VStack {
                    ForEach(0...70, id: \.self) { _ in
                        Text("Text text")
                    }
                }.frame(minWidth: 0, maxWidth: .infinity)
                    .background(Color(UIColor.red))
            }
            .navigationBarTitle("Title", displayMode: .large)
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

It would produce a view that looks like this: enter image description here

enter image description here

I know it's not the full solution because of the top safe edge, but hopefully it helps you get a little closer.

PS Ive tried ignoring the top safe edge but it causes issues with nav bar spacing