So, I want a List in SwiftUI, where the border of each row depends on some function of the contents of the row. Normally I can do this easily with .border()
but List seems to take care of the styling for the elements itself, adding padding and that.
The closest I have is below, which is quite far from what I'm after. This produces the borders around the text fields, but I want instead to produce borders around the whole cell.
struct ListDemoView: View {
@State private var nums: [Int] = [1, 2, 3, 4, 5]
var body: some View {
List (nums, id: \.self) { num in
Section {
Text("Num: \(num)")
}
.border(num % 2 == 0 ? Color.red : Color.blue)
}
}
}
A simple way to add a border is to stroke the border of the .listRowBackground
. This way, the row insets can be left at the default.
When the list style is .insetGrouped
(the default), the List
applies its own rounded rectangle as clip shape to the section. The corner radius for this clip shape appears to be about 10.
To avoid thinning at the corners, the rounded rectangle for the rows needs to use a corner radius at least as large as the clip shape for the section, in other words >= 10.
If the border is stroked using .stroke
then the clip shape also clips half the width of the border. Use .strokeBorder
to keep the stroke inside the border of the shape.
Btw, the issue of the clip shape affects all the answers to this post.
List (nums, id: \.self) { num in
Section {
Text("Num: \(num)")
}
.listRowBackground(
RoundedRectangle(cornerRadius: 10)
.fill(.background)
.strokeBorder(num % 2 == 0 ? Color.red : Color.blue, lineWidth: 2)
)
}
This approach will add a border around each row of the list. Currently, each row of the list is wrapped in its own Section
, so the gaps between rows are actually gaps between sections. You can achieve the same look by removing the Section
and adding .listRowSpacing
to the List
:
List (nums, id: \.self) { num in
Text("Num: \(num)")
.listRowBackground(
RoundedRectangle(cornerRadius: 10)
.fill(.background)
.strokeBorder(num % 2 == 0 ? Color.red : Color.blue, lineWidth: 2)
)
}
.listRowSpacing(35)