50

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

juhan_h
  • 3,965
  • 4
  • 29
  • 35
Ivan Vorobei
  • 629
  • 1
  • 6
  • 6

12 Answers12

45

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")
            }
        }
    }
}
Machavity
  • 30,841
  • 27
  • 92
  • 100
LJ White
  • 615
  • 6
  • 6
  • 8
    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... – neywen Feb 11 '20 at 16:33
  • By the way works with LinearGradient too! – Brogrammer Jan 09 '23 at 22:13
20

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/

lewis
  • 2,936
  • 2
  • 37
  • 72
JimCSanJose
  • 233
  • 2
  • 6
14

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")
    }
  }
}
FRIDDAY
  • 3,781
  • 1
  • 29
  • 43
6

For the nav bar in iOS 16 +

.toolbarBackground(.red, for: .navigationBar)

0xWood
  • 1,326
  • 12
  • 15
  • 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:)` – codingFriend1 Dec 22 '22 at 15:25
5

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

Mattis Schulte
  • 639
  • 1
  • 10
  • 18
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.stack.imgur.com/G5PXt.jpg

Alex
  • 71
  • 1
  • 6
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
PostCodeism
  • 1,070
  • 1
  • 12
  • 20
1

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)
omar
  • 173
  • 1
  • 13
  • 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) – Ivan Vorobei Jul 07 '19 at 15:55
  • 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? – omar Jul 07 '19 at 17:36
  • 2
    Not scrolling navigation bar from large state to base – Ivan Vorobei Jul 07 '19 at 17:52
  • Holy crap. I can't believe this hack is needed just for something that should have a backgroundColor attribute. – PostCodeism Aug 20 '19 at 17:20
  • 2
    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. – alexisSchreier Dec 11 '19 at 07:45
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)
        }
    }
 }
stosha
  • 2,108
  • 2
  • 27
  • 29
0

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

alexis
  • 31
  • 5
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

l1Dan
  • 9
  • 6
0

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
            }
Vkharb
  • 856
  • 11
  • 19