ioslistviewswiftui

Apply custom border to each row in a List with SwiftUI


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

    }
}

enter image description here


Solution

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

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

    Screenshot


    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)