29

I can't change background color of a view if i List static items. this my code:

NavigationView {
    ZStack {
        Color("AppBackgroundColor").edgesIgnoringSafeArea(.all)
        List {
            Section(header: Text("Now in theaters")) {
                ScrollMovies(type: .currentMoviesInTheater)
            }
            Section(header: Text("Popular movies")) {
                ScrollMovies(type: .popularMovies)
            }
        }.listStyle(.grouped)
    }
}
2
  • Do you want to Change List background color or ZStack background color? Commented Jul 22, 2019 at 8:49
  • i want to change the background of all view. Commented Jul 22, 2019 at 10:24

9 Answers 9

44

iOS 16

Since Xcode 14 beta 3, You can change the background of all lists and scrollable contents using this modifier:

.scrollContentBackground(.hidden)

You can pass in .hidden to make it transparent. So you can see the color or image underneath.


iOS 15 and below

All SwiftUI's Lists are backed by a UITableView (until iOS 16). so you need to change the background color of the tableView. You make it clear so other views will be visible underneath it:

struct ContentView: View {
    
    init(){
        UITableView.appearance().backgroundColor = .clear
    }
        
    var body: some View {
        Form {
            Section(header: Text("First Section")) {
                Text("First cell")
            }
            Section(header: Text("Second Section")) {
                Text("First cell")
            }
        }
        .background(Color.yellow)
    }
}

Now you can use Any background (including all Colors) you want

Preview

Note that those top and bottom white areas are the safe areas and you can use the .edgesIgnoringSafeArea() modifier to get rid of them.

Also note that List with the .listStyle(GroupedListStyle()) modifier can be replaced by a simple Form. But keep in mind that SwiftUI controls behave differently depending on their enclosing view.

Also you may want to set the UITableViewCell's background color to clear as well for plain tableviews

Sign up to request clarification or add additional context in comments.

6 Comments

Good answer, but this only works for iOS. Do you know how to make the same on macOS?
I will look into it @Lupurus and let you know
Note that a List in GroupedStyle is NOT the same as Form. SwiftUI controls behave differently depending in their enclosing view.
@Lupurus i added a solution for macOS if you want stackoverflow.com/a/60424034/4100181
This doesn't work anymore on iOS 16 :(
|
27
@State var users: [String] = ["User 1",
                              "User 2",
                              "User 3",
                              "User 4"]

init(){
    UITableView.appearance().backgroundColor = .red
    UITableViewCell.appearance().backgroundColor = .red
    UITableView.appearance().tableFooterView = UIView()
}

var body: some View {
    List(users, id: \.self){ user in
        Text(user)
    }
    .background(Color.red)
}

PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())

2 Comments

This doesn't work when you have a gradient background behind the list.
Using the UITableView.appearance() will affect all lists in the application. See my suggested answer below.
9

List cannot be "painted". Please use the following instead:

List of items:

ForEach(items) { item in
    HStack {
        Text(item)
    }
}.background(Color.red)

Scrollable list of items:

ScrollView {
    ForEach(items) { item in
        HStack {
            Text(item)
        }
    }.background(Color.red)
}

In your case:

VStack { // or HStack for horizontal alignment
    Section(header: Text("Now in theaters")) {
        ScrollMovies(type: .currentMoviesInTheater)
    }
    Section(header: Text("Popular movies")) {
        ScrollMovies(type: .popularMovies)
    }
}.background(Color.red)

2 Comments

This is the best answer, I also want to leave a comment that you can use a @State in a search bar to filter your ForEach as you would a normal List aswell. Generic Example: ForEach(items.filter({ searchText.isEmpty ? true : $0.name.contains(searchText) })) { item in HStack {Text(item)}} will also work!!!
What do you mean by "painted"?
6

Using UITableView.appearance().backgroundColor can affect the background colour of all List controls in the app. If you only want one particular view to be affected, as a workaround, you can set it onAppear and set it back to the default onDisappear.

import SwiftUI
import PlaygroundSupport

struct PlaygroundRootView: View {
    @State var users: [String] = ["User 1",
                                  "User 2",
                                  "User 3",
                                  "User 4"]
    var body: some View {
        Text("List")
        List(users, id: \.self){ user in
            Text(user)
        }
        .onAppear(perform: {
            // cache the current background color
            UITableView.appearance().backgroundColor = UIColor.red
        })
        .onDisappear(perform: {
            // reset the background color to the cached value
            UITableView.appearance().backgroundColor = UIColor.systemBackground
        })
    }
}
PlaygroundPage.current.setLiveView(PlaygroundRootView())

Comments

4

You can provide a modifier for the items in the list

NavigationView {
        ZStack {
            Color("AppBackgroundColor").edgesIgnoringSafeArea(.all)
            List {
                Section(header: Text("Now in theaters")) {
                    ScrollMovies(type: .currentMoviesInTheater)
                    .listRowBackground(Color.blue) // << Here
                }
                Section(header: Text("Popular movies")) {
                    ScrollMovies(type: .popularMovies)
                    .listRowBackground(Color.green)  // << And here
                }
            }.listStyle(.grouped)
        }
    }

1 Comment

Not the correct answer - you lose Sticky headers because of the Grouped list style.
4

For SwiftUI on macOS this works :

extension NSTableView {
    open override func viewDidMoveToWindow() {
        super.viewDidMoveToWindow()

        // set the background color of every list to red
        backgroundColor = .red
    }
}

It will set the background color of every list to red (in that example).

Comments

3

Easiest way to do this for now is just to use UIAppearance proxy. SwiftUI is young so there's a couple of features not fully implemented correctly by Apple yet.

UITableView.appearance().backgroundColor = .red

1 Comment

This combined with listRowBackground() on List rows solved it for me. The result is consistent even when scrolling the view, which is what I wanted to achieve.
1

A bit late to the party, but this may help. I use a combination of:

  • Setting the UITableView.appearance appearance
  • Setting the UITableViewCell.appearance appearance
  • Settings the List listRowBackground modifier.

Setting the appearance affects the entire app, so you may want to reset it to other values where applicable.

Sample code:

struct ContentView: View {
    var body: some View {
        
        let items = ["Donald", "Daffy", "Mickey", "Minnie", "Goofy"]

        UITableView.appearance().backgroundColor = .clear
        UITableViewCell.appearance().backgroundColor = .clear
        
        return ZStack {
            Color.yellow
                .edgesIgnoringSafeArea(.all)
            List {
                Section(header: Text("Header"), footer: Text("Footer")) {
                    ForEach(items, id: \.self) { item in
                        HStack {
                            Image(systemName: "shield.checkerboard")
                                .font(.system(size: 40))
                            Text(item)
                                .foregroundColor(.white)
                        }
                        .padding([.top, .bottom])
                    }
                    .listRowBackground(Color.orange))
                }
                .foregroundColor(.white)
                .font(.title3)
            }
            .listStyle(InsetGroupedListStyle())
        }
        
    }
}

Comments

-3

since, you are asking for changing the background color of view,

you can use .colorMultiply() for that.

Code:

var body: some View {
        VStack {
            ZStack {
                List {
                    Section(header: Text("Now in theaters")) {
                        Text("Row1")
                    }
                    Section(header: Text("Popular movies")) {
                        Text("Row2")
                    }

                    /*Section(header: Text("Now in theaters")) {
                        ScrollMovies(type: .currentMoviesInTheater)
                    }
                    Section(header: Text("Popular movies")) {
                        ScrollMovies(type: .popularMovies)
                    } */
                }.listStyle(.grouped)
            }.colorMultiply(Color.yellow)
        }
}

Output:

enter image description here

3 Comments

This is not expected answer. colorMultiply() tints the whole list, including cells, which is not the intention, and it is not same as list background color. There is background modifier (.background(Color.red) for List and for every other view, but it doesn't work for lists.
I think this is a reasonable workaround in some circumstances.
Try to display an image in one of the cells... the yellow color will be applied to them as well

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.