One can use .listRowBackground
to change the color of a list row in SwiftUI
.
I am trying to use this to color the background of a row conditionally.
What's the correct color to persist the system's default background color for a row where the condition does not apply?
Color.clear
is wrong, cause it really clears the background instead of falling back to the default. Color.white
also is wrong, because it is not agnostic to dark mode...
So, what's the system agnostic default background color of a list in SwiftUI?
Consider the following (Playground) code:
import SwiftUI
import PlaygroundSupport
struct Item: Identifiable {
let id = UUID()
var completed: Bool
}
struct ListView: View {
let items = [
Item(completed: true),
Item(completed: false),
Item(completed: false),
Item(completed: false),
Item(completed: true),
]
var body: some View {
List {
ForEach(items) { item in
VStack(alignment: .leading) {
Text(item.id.uuidString)
}
.listRowBackground(item.completed ? Color.green : Color.clear)
}
}
}
}
PlaygroundPage.current.setLiveView(ListView())
The preview looks like this (and please be aware the background of the rows is cleared out):
If I comment out .listRowBackground(item.completed ? Color.green : Color.clear)
, the preview is this:
I can help myself with the workaround of introducing a conditional view modifier:
extension View {
@ViewBuilder func `if`<Content: View>(_ condition: @autoclosure () -> Bool, transform: (Self) -> Content) -> some View {
if condition() {
transform(self)
} else {
self
}
}
}
I can then apply this with
.if(item.completed) { view in
view
.listRowBackground(Color.green)
}
This does result in the desired view–but is a bit gnarly. There must be a better way I would hope...
I found the solution–by simply trying out .none
for the false branch of the ternary expression:
.listRowBackground(item.completed ? Color.green : .none)
does exactly what I want. Amazes me that I couldn't find any mention on this neither in the documentation nor anywhere else…