SwiftUI background color of List Mac OS
Update: 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.
How to reliably retrieve a window's background color on macOS with SwiftUI?
Swifty way to get Window Background
The window's background is not composed by a color, is a NSVisualEffectView
with .windowBackground
as material
.
You can achieve that with this code:
struct EffectView: NSViewRepresentable {
@State var material: NSVisualEffectView.Material = .headerView
@State var blendingMode: NSVisualEffectView.BlendingMode = .withinWindow
func makeNSView(context: Context) -> NSVisualEffectView {
let view = NSVisualEffectView()
view.material = material
view.blendingMode = blendingMode
return view
}
func updateNSView(_ nsView: NSVisualEffectView, context: Context) {
nsView.material = material
nsView.blendingMode = blendingMode
}
}
And apply that to your view:
struct ContentView: View {
var body: some View {
EffectView(material: .windowBackground)
.overlay(Text("Window Real Background"))
.padding(30)
}
}
The output is this (nothing to see because it mimetizes with background):
The reason why the background is an NSVisualEffectView is because the Window Tinting of macOS Big Sur, that changes the background according to wallpaper predominant color:
iOS 16 SwiftUI List Background
iOS 16
Update: Xcode 14b3+
Just use new modifier:
List {
Text("Item 1")
Text("Item 2")
Text("Item 3")
}
.scrollContentBackground(Color.red) // << here !!
// .scrollContentBackground(Color.clear) // << transparent !!
// .scrollContentBackground(.hidden) // << can be combined with above !!
Original
Now they use UICollectionView
for backend, so an updated workaround is to change corresponding background colors:
Main part:
extension UICollectionReusableView {
override open var backgroundColor: UIColor? {
get { .clear }
set { }
// default separators use same color as background
// so to have it same but new (say red) it can be
// used as below, otherwise we just need custom separators
//
// set { super.backgroundColor = .red }
}
}
struct ContentView: View {
init() {
UICollectionView.appearance().backgroundColor = .clear
}
//...
Test module on GitHub
How do I modify the background color of a List in SwiftUI?
Ok, I found the solution for coloring the list rows:
struct TestRow: View {
var body: some View {
Text("This is a row!")
.listRowBackground(Color.green)
}
}
and then in body:
List {
TestRow()
TestRow()
TestRow()
}
This works as I expect, but I have yet to find out how to then remove the dividing lines between the rows...
What's the default color for the background of a SwiftUI List?
Short answer: it looks like it is UIColor.secondarySystemBackground
Long answer:
I have tried Digital Color Meter app the sam as you did. It shows this RGB values: 242, 242, 247.
I have created such color:
Here is my code:
import SwiftUI
extension Color {
public static let ListBGColor = Color("ListBGColor")
}
struct ContentView: View {
var body: some View {
List {
ForEach(0..<5) {_ in
Text("Hello, world!")
.padding()
}
.listRowBackground(Color.ListBGColor)
}
.listStyle(InsetGroupedListStyle())
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Result: the same color as the background (testes on Simulator and iPhone):
SwiftUI List color background
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 List
s 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 view
s 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 Color
s) you want
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
Related Topics
What Does the '@' Symbol Mean in Swift
How to Calculate the 21! (21 Factorial) in Swift
Reference as Key in Swift Dictionary
Swift 4.2 Imagepickercontroller Issue
Viewcontroller Slide Animation
How to Reference Swift Playground Itself
When and How to Use @Noreturn Attribute in Swift
Swift 2 Protocol Extension Not Calling Overridden Method Correctly
Draw a Hole in a Rectangle with Spritekit
"Unrecognized Selector Sent to Instance" in Swift
How to Write Inline Assembly in Swift
Swift: How to Delete Part of Audio
Division Not Working Properly in Swift
Ondelete Causing Nsrangeexception
Could Not Find an Overload for '/' That Accepts the Supplied Arguments