62

I want to change background color for full screen. I am using NavigationView, and I want to set Gray color for background (not default white)

struct ContentView : View {
    var body: some View {
        NavigationView {
            ScrollView {
                Text("Example")
            }
            .navigationBarTitle("titl")
        }
    }
}

Setting .background(Color.red) does not work in any place.

preview

15 Answers 15

51

If you just embed your content in the NavigationView within a ZStack you should be able to throw the color in underneath your main content.

struct ContentView : View {
    var body: some View {
        NavigationView {
            ZStack {
                Color.red.edgesIgnoringSafeArea(.all)
                ScrollView {
                    Text("Example")
                }
                .navigationBarTitle("title")
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

in my case, that was working at a first glance, but I found out that it makes my app crash. My "ContentView" is already in a ZStack, and the crash occurs when this "ContentView" is removed from the tree. To be more precise, it's the use of "edgesIgnoringSafeArea" on the color that makes my app crash. So for now, I still have to found a valid way of changing the Navigation bar color. I'm afraid there's no solution for now...
By the way works with LinearGradient too!
22

Adding to Mattis Schulte's answer, one of the side effects I've encountered is that the status bar will not inherit the background color.

However when you scroll a List (for example) up toward the top of the view and iOS switches to an inline title view (with the centered NavigationBarTitle) it does color in the status bar area leaving a fairly undesirable user experience.

The workaround I was able to use is:

import SwiftUI

let coloredNavAppearance = UINavigationBarAppearance()
   
struct ListView: View {

    init() {
        coloredNavAppearance.configureWithOpaqueBackground()
        coloredNavAppearance.backgroundColor = .systemBlue
        coloredNavAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
        coloredNavAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
               
        UINavigationBar.appearance().standardAppearance = coloredNavAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = coloredNavAppearance

    }

    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("General")) {
                    HStack {
                        Text("ListView #1")
                        Spacer()
                        Text("data")
                            .multilineTextAlignment(.trailing)
                    }
                    HStack {
                        Text("ListView #2")
                        Spacer()
                        Text("data")
                            .multilineTextAlignment(.trailing)
                    }
                }

            }
            .navigationBarTitle("NavBar Title")
        }
    }
}


struct ListView_Previews: PreviewProvider {
    static var previews: some View {
        ListView()
    }
}

Hope this helps someone else. Credit to https://sarunw.com/posts/uinavigationbar-changes-in-ios13/

1 Comment

Thank you. I didn't even know what key I should search to fix this issue.
15

A newest solution is having an extension for UINavigationController, as below:

extension UINavigationController {
    override open func viewDidLoad() {
        super.viewDidLoad()

    let standard = UINavigationBarAppearance()
    standard.backgroundColor = .red //When you scroll or you have title (small one)

    let compact = UINavigationBarAppearance()
    compact.backgroundColor = .green //compact-height

    let scrollEdge = UINavigationBarAppearance()
    scrollEdge.backgroundColor = .blue //When you have large title

    navigationBar.standardAppearance = standard
    navigationBar.compactAppearance = compact
    navigationBar.scrollEdgeAppearance = scrollEdge
 }
}

OR, The old one:

Inside your struct initializer change UITableView color, as below:

struct ContentView : View {
init() {
    UITableView.appearance().backgroundColor = .red
    }
var body: some View {
    NavigationView {
        ScrollView {
            Text("Example")
        }
        .navigationBarTitle("title")
    }
  }
}

3 Comments

Will this configure the Navigation bar for the entire app?
@aheze, Yes, add it inside appdelegate.
Can you use the extension solution on UITableView as well?
7

For the nav bar in iOS 16 +

.toolbarBackground(.red, for: .navigationBar)

1 Comment

Nice! However, this seems to only take effect when the toolbar is not translucent. So either when the user scrolls, or if you manually set the navigation bar to be always visible with toolbar(visible: for:)
5

Just add this to the initializer of your code UIScrollView.appearance().backgroundColor = UIColor.red. But unfortunately, this solution has many side effects.

Comments

3

Here is my solution as none of the others worked in my case so I thought I would share..

So for the Navigation header bar colour, add an initialiser like this:

struct ContentView: View {
    init() {
        UINavigationBar.appearance().backgroundColor = .red
    }
    var body: some View {
        NavigationView {
            ScrollView {
                ...
            }
        }
    }
}

And then for editing the ScrollView background color, you can do something like this: I have done for ListView but you can do it for ScrollView.

struct ListBackgroundColor: ViewModifier {

    let color: UIColor

    func body(content: Content) -> some View {
        content
            .onAppear() {
                UITableView.appearance().backgroundColor = self.color
                //(Optional) Edit colour of cell background
                UITableViewCell.appearance().backgroundColor = self.color
            }
    }
}   

extension View {
    func listBackgroundColor(color: UIColor) -> some View {
        ModifiedContent(content: self, modifier: ListBackgroundColor(color: color))
    }

}

UI Example https://i.sstatic.net/G5PXt.jpg

Comments

2

One little hack that you can do is add a text view that doesnt have any text in it and add the background color to what you want, something like the following:

Text(" ")
    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
    .background(Color.red)
    .edgesIgnoringSafeArea(.all)

5 Comments

It code add color swift NavigationView { ZStack { Text(" ") .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity) .background(Color.red) .edgesIgnoringSafeArea(.all) ScrollView { ChooseView() ChooseView() } } .navigationBarTitle("Title") } But scroll not work correct (navigation not translate)
The view is not scrolling? Are you sure that the scrollview is on top of the text view? can you upload a picture of the data that you are trying to scroll? In addition, if you remove the textview can you scroll?
Not scrolling navigation bar from large state to base
Holy crap. I can't believe this hack is needed just for something that should have a backgroundColor attribute.
It's a hack.. So you should expect bugs when you use it. I would stay away from this solution if you don't want problems down the line... like not being able to scroll.
2

Ok I just tried omar's solution, and unfortunately it doesn't work if there are any other views in the stack.

So the best answer I've seen for now that actually changes the underlying background color of the NavigationView (in OP's original question) is just setting the background color on the UIView appearance, as eluded to in this answer:

UIView.appearance().backgroundColor = UIColor.red

2 Comments

When I try your solution, I get the desired background color but everything else disappears.
Me also got the same issue as @MattisSchulte.
1

it's quite complicated to change bg color for NavigationView and keep it working properly like minification / magnification during content scrolling and also keeping safe areas

NavigationView-color-customisation on github here i posted common problems and solutions about color customisation in SwiftUI app

also if you really want to change bg color in ALL navgiationViews, prev comment's first part about Extension on UINavigationController looks good

Comments

1

for iOS 14 and less

UINavigationBar.appearance().barTintColor = UIColor.red

for iOS 15

NavigationView {
            ZStack(alignment: .top) {
                GeometryReader { reader in
                    Color.red
                        .frame(height: reader.safeAreaInsets.top, alignment: .top)
                        .ignoresSafeArea()
                }

                // your content view
            }

Comments

1

For iOS 16 following code makes black background for whole screen:

 var body: some View {
    GeometryReader { geometry in
        NavigationView {
            List {
                ForEach(solutions) { solution in
                }
                .listRowBackground(Color.black)
            }
            .listStyle(.plain)
            .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
            .navigationBarTitleDisplayMode(.inline)
            .navigationTitle("My Solutions")
            .toolbar {
                Button("Add") {
                    addSolution()
                }
                .foregroundColor(.white)
            }
            .background(.black)
        }
    }
 }

Comments

1

Try presentationBackground. You can also do colors or .clear in place of .ultraThinMaterial.

struct ContentView : View {
    var body: some View {
        NavigationView {
            Text("Example")
        }
        .presentationBackground(.ultraThinMaterial)
    }
}

Comments

0

NavigationView in SwiftUI and UINavigationBar in UIKit are just as cumbersome, and I have a third-party open source solution for iOS system navigation bars that I hope will help you solve the problem.

Git repo: NXNavigationExtension

Change NavigationView color:

struct ContentView: View {
    
    var body: some View {
        NavigationView {
            NavigationLink {
                Text("Pop")
                    .padding()
                    .useNXNavigationView(onPrepareConfiguration: { configuration in
                        // Page2
                        configuration.navigationBarAppearance.backgroundColor = .green
                    })
            } label: {
                Text("Push")
                    .padding()
                    .useNXNavigationView(onPrepareConfiguration: { configuration in
                        // Page1
                        configuration.navigationBarAppearance.backgroundColor = .red
                    })
            }
        }
        .navigationViewStyle(.stack)
    }
    
}

📝 example

Comments

0

With the help of this article. I updated the color of my navigation view in swiftUI.

NavigationView {
    VStack{}
    .navigationBarColor(.black, tintColor: .white) 👈
}

This method is not available in the View class so write an extension

extension View {

func navigationBarColor(_ backgroundColor: Color?, tintColor: Color?) -> some View {
    self.modifier(NavigationBarModifier(backgroundColor: UIColor(backgroundColor ?? .white), tintColor: UIColor(tintColor ?? .black)))
}

}

We don't have the NavigationBarModifier right now, so we need to add this class in our code.

struct NavigationBarModifier: ViewModifier {
    var backgroundColor: UIColor?

init(backgroundColor: UIColor?, tintColor: UIColor?) {
    self.backgroundColor = backgroundColor

    let coloredAppearance = UINavigationBarAppearance()
    coloredAppearance.configureWithTransparentBackground()
    coloredAppearance.backgroundColor = .clear
    coloredAppearance.titleTextAttributes = [.foregroundColor: tintColor as Any]
    coloredAppearance.largeTitleTextAttributes = [.foregroundColor: tintColor as Any]

    UINavigationBar.appearance().standardAppearance = coloredAppearance
    UINavigationBar.appearance().compactAppearance = coloredAppearance
    UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
    UINavigationBar.appearance().tintColor = tintColor

}

func body(content: Content) -> some View {
    ZStack{
        content
        VStack {
            GeometryReader { geometry in
                Color(self.backgroundColor ?? .clear)
                    .frame(height: geometry.safeAreaInsets.top)
                    .edgesIgnoringSafeArea(.top)
                Spacer()
            }
        }
    }
}
}

Now Color of the Navigation View is changed.

Comments

0

I think I found the solution.

First, use NavigationStack. On a side note, if you put .background(.red) on the ScrollView, you actually have a red background color. However I think what you want is to have a persistent background color when navigation happens in the NavigationStack, no matter what view gets pushed into it. Normally, any view that is pushed onto that, will have its own background color, overriding anything that is behind that, and Color.clear will have no effect, it will always have at least a white background that you can't remove.

See this solution to make the NavigationStack itself transparent: [1]: Remove background from NavigationStack in SwiftUI

Then use this to remove the default white(or any) background color from any new view you push onto the NavigationStack.

.introspect(.viewController, on: .iOS(.v13, .v14, .v15, .v16, .v17, .v18)) {
  $0.view.backgroundColor = .clear
}

Now you have a fully transparent NavigationStack and you can use a ZStack (or something else) to wrap around the NavigationStack and set a normal .background(Color.anything) and you will have a persistent background color behind the NavigationStack.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.