28

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)
    }
}
pawello2222
  • 46,897
  • 22
  • 145
  • 209

9 Answers9

39

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

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
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())
grg
  • 5,023
  • 3
  • 34
  • 50
Enzo N. Digiano
  • 370
  • 3
  • 6
8

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)
ricardopereira
  • 11,118
  • 5
  • 63
  • 81
DmitryZ
  • 81
  • 1
  • 4
  • 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!!! – DaWiseguy Jul 10 '20 at 20:36
  • What do you mean by "painted"? – Peter Schorn Dec 13 '20 at 22:46
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())

Andy Thomas
  • 1,367
  • 2
  • 14
  • 30
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)
        }
    }

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).

Anthony
  • 1,155
  • 10
  • 17
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

mm282
  • 453
  • 3
  • 7
  • 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. – Stefan Edberg Apr 28 '20 at 09:35
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())
        }
        
    }
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
titusmagnus
  • 2,014
  • 3
  • 23
  • 23
-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

Ketan Odedra
  • 1,215
  • 10
  • 35
  • 8
    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. – Vladimir88dev Jul 24 '19 at 07:48
  • 1
    I think this is a reasonable workaround in some circumstances. – Bart van Kuik Sep 24 '19 at 09:17
  • 1
    Try to display an image in one of the cells... the yellow color will be applied to them as well – Tiziano Coroneo Nov 12 '19 at 14:11