45

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?

M Reza
  • 18,350
  • 14
  • 66
  • 71
  • 2
    In UIKit you fix this by setting the table view's `footerView` to an empty view. Maybe SwiftUI supports a List footer. – rmaddy Jun 07 '19 at 16:59

10 Answers10

36

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.

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
  • At this time, neither "tableFooterView" nor "separatorStyle" is reachable. – Faruk Mar 23 '20 at 14:31
  • For IOS 14, when we used LazyVStack we loose the selection and reordering features of a list. So, it's not a valid solution for all of the cases. – emreoktem Nov 29 '20 at 10:57
  • "OS 14 doesn't show extra separators below the list by default." Does this mean there is a way to show separators below the list? Because I have the exact opposite scenario where I would like to to show empty rows. – bcause Jan 02 '21 at 00:13
21

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.

mginn
  • 16,036
  • 4
  • 26
  • 54
  • any hints how to add some nice animation for reloading? when data will change? – Lifeplus Jun 13 '19 at 15:50
  • 1
    @Lifeplus that's a good point. For now, I'd use one of the other answers which uses a List, and the ability to manipulate separators should be added soon. – mginn Jun 16 '19 at 17:12
  • 3
    Not bad solution, but we need to not forgot about "reusable" view (for tableview / list). if we use scrollview as solution, we automatically up memory usage. – Sergey Krasiuk Aug 11 '19 at 12:44
  • 1
    Also it's not an option if we need "Edit" functionality. Like ability to delete/move the rows. – RustamG Jul 21 '20 at 10:53
  • 1
    @RustamG you're right. Frankly, I'm a little disappointed with the bare minimum customization for standard elements provided by SwiftUI so far. I get that it's new, but if it's the future for Apple platforms, you'd think they'd have a huge push behind it. – mginn Jul 21 '20 at 18:06
18

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 }
halfer
  • 19,824
  • 17
  • 99
  • 186
KitKit
  • 8,549
  • 12
  • 56
  • 82
14

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

KirinSoo
  • 337
  • 2
  • 11
9

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

Odrakir
  • 4,254
  • 1
  • 20
  • 52
4

iOS 13 builds only:

You can add this, for remove separator.

UITableView.appearance().separatorColor = .clear
sam-w
  • 7,478
  • 1
  • 47
  • 77
YanSte
  • 10,661
  • 3
  • 57
  • 53
3

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.

grg
  • 5,023
  • 3
  • 34
  • 50
CrazyPro007
  • 1,006
  • 9
  • 15
2

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.

SMP
  • 1,629
  • 7
  • 15
  • Thanks, is there any way to remove the extra dividers this adds to the top and bottom of the list? – M Reza Jun 08 '19 at 04:21
  • As I mentioned you can create own and use it instead of Text, maybe a view with 1 pt height. – SMP Jun 08 '19 at 05:51
0

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

Amir.n3t
  • 2,859
  • 3
  • 21
  • 28
0

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()
Nayan Dave
  • 1,078
  • 1
  • 8
  • 30
Mia
  • 1