44
votes

I've created a simple List as below, but there are extra separators below it.

List {
  Text("Item 1")
  Text("Item 2")
  Text("Item 3")
}

Result:

enter image description here

I've tried embedding the List inside a VStack and adding Spacer() like below code but it's not working properly. It removes about half of the empty cells.

VStack{
  List {
    Text("Item 1")
    Text("Item 2")
    Text("Item 3")
  }
  Spacer()
}

How would I remove these extra separators in SwiftUI?

10
In UIKit you fix this by setting the table view's footerView to an empty view. Maybe SwiftUI supports a List footer.rmaddy

10 Answers

36
votes

iOS 14:

iOS 14 doesn't show extra separators below the list by default and to removing all separators, you need to use a LazyVStack inside a ScrollView instead. (because iOS is NOT supporting appearance for SwiftUI lists anymore).

LazyVStack Preview


iOS 13:

⚠️ This method is deprecated and it's not working from iOS 14

No need for Section or .grouped style!

There is a UITableView behind SwiftUI's List for iOS 13. So to remove

- Extra separators (below the list):

you need a tableFooterView and to remove. Note that iOS 14 doesn't show extra separators below the list by default.

- All separators (including the actual ones):

you need separatorStyle to be .none

init() {
    if #available(iOS 14.0, *) { 
        // iOS 14 doesn't have extra separators below the list by default.
    } else {
        // To remove only extra separators below the list:
        UITableView.appearance().tableFooterView = UIView()
    }

    // To remove all separators including the actual ones:
    UITableView.appearance().separatorStyle = .none
}

var body: some View {
    List {
        Text("Item 1")
        Text("Item 2")
        Text("Item 3")
    }
}

Note that it eliminates all tables/lists's separators. So you can toggle it in a methods like onAppear() or etc. as you wish.

21
votes

It's not a perfect solution, but you could use a ScrollView, where each cell is created using a ForEach call, and the dividers are created using Divider().

Edit: I spoke with Apple engineers at WWDC about this. They have heard lots of feedback regarding removing/changing dividers. However, for now my above answer is their recommendation.

18
votes

This is for iOS 13 builds only.

Use onAppear modify a separator style through UITableView and restore to the initial state with onDisappear

List {}
.onAppear { UITableView.appearance().separatorStyle = .none }
.onDisappear { UITableView.appearance().separatorStyle = .singleLine }
14
votes

Not an ideal solution, but you can make the list style .grouped by .listStyle(.grouped) which removes any empty cells that may come below.

9
votes

Adding a white rectangle as a footer and with 0 EdgeInsets worked for me:

struct Footer: View {
    var body: some View {
        Rectangle()
            .foregroundColor(.white)
            .listRowInsets(EdgeInsets())
    }
}

struct Timeline : View {
    var body: some View {
        List {
            Section(footer: Footer()) {
                Text("Item 1")
                Text("Item 2")
                Text("Item 3")
            }
        }
    }
}

The only problem is it also adds a Header and I'm not sure how to get rid of it.

enter image description here

3
votes

iOS 13 builds only:

You can add this, for remove separator.

UITableView.appearance().separatorColor = .clear
3
votes

Two ways of doing that:

struct ContentView: View {
    
    var body: some View {
        
        List {
                Text("One")
                Text("Two")
                Text("Three")
        }.listStyle(GroupedListStyle())
    }
}
struct ContentView: View {
    
    var body: some View {
        
        List {
            Section(header: Text("Header"), footer: Text("Footer")) {
                Text("One")
                Text("Two")
                Text("Three")
            }
        }
    }
}

I recommend grouped list style.

2
votes

Here's one way.

List {
         Section(footer: Text(""))) {
                Text("One")
                Text("Two")
                Text("Three")
            }
     }

Instead of the Text view in the footer, you can create your own. Note -I tried EmptyView() but that doesn't actually remove the redundant separators.

0
votes

Try this, if you want to use the section, There's still a footer visible with this:

List {
    Section(footer: Text("")) {
        Text("My text")
    }
    EmptyView()
}

enter image description here

I came up with a hacky way to hide footer in case you don't have any section:

List {
    Text("Item 1")
    Text("Item 2")

    // Adding empty section with footer
    Section(footer:
        Rectangle()
            .foregroundColor(.clear)
            .background(Color(.systemBackground))){EmptyView()}
            .padding(.horizontal, -15)
}

enter image description here

0
votes

For unknown reason, I had this problem in tableView even after iOS14, even though the answer above that there will be no longer extra separator lines in default.

The method I use to solve it is to set footerView to vacant UIView, as in that same answer.

your_tableView.tableFooterView = UIView()