Search code examples
swiftmacosswiftui

SwiftUI background color of List Mac OS


I am using a ListView in Mac OS. I am trying to change that background color of that ListView. However, it is not that easy as expected.

I tried using .background(Color(.red)) attribute on the ListView. That didn't change anything.

I could only find .listRowBackground(Color(.red))which had an influence on the table rows. However, the other background wasn't effected.

I prepared a little demo to demonstrate:

In my view body:

  VStack
    {
        List()
        {
            Text("Test")
                .listRowBackground(Color.green)

            Text("Test")
                .listRowBackground(Color.green)

            Text("Test")
                .listRowBackground(Color.green)

        }.background(Color(.red))

    }.background(Color(.red))

That is the result I get:

enter image description here

The main background does not change. I read about a solution changing the UITableView.appearance but that is not possible for me in SwiftUI for Mac OS.

Thanks in advance


Solution

  • Update 2: I haven't verified this, but user1046037 says there is a new API available for changing scrolling backgrounds: scrollContentBackground.

    Update 1: I found a much better way to remove a list's background without affecting the whole app: by using Introspect.

    import Introspect
    import SwiftUI
    
    extension List {
      /// List on macOS uses an opaque background with no option for
      /// removing/changing it. listRowBackground() doesn't work either.
      /// This workaround works because List is backed by NSTableView.
      func removeBackground() -> some View {
        return introspectTableView { tableView in
          tableView.backgroundColor = .clear
          tableView.enclosingScrollView!.drawsBackground = false
        }
      }
    }
    

    Usage:

    List {
      ForEach(items) { item in
        ...
      }
    }.removeBackground()
    

    Old answer:

    @Asperi's answer works, but only until the window is resized. Here's another workaround for overriding List's color:

    extension NSTableView {
      open override func viewDidMoveToWindow() {
        super.viewDidMoveToWindow()
    
        backgroundColor = NSColor.clear
        enclosingScrollView!.drawsBackground = false
      }
    }
    

    A potential downside is that this will affect all lists in the app.