How to remove "row" separators/dividers from a List in SwiftUI?
Solution 1
iOS 15:
This year Apple introduced a new modifier .listRowSeparator
that can be used to style the separators. you can pass .hidden
to hide it:
List {
ForEach(items, id:\.self) {
Text("Row \($0)")
.listRowSeparator(.hidden)
}
}
iOS 14
Apple introduced LazyVStack
In iOS 14. you may consider using it instead of list for this:
ScrollView {
LazyVStack {
ForEach((1...100), id: \.self) {
Text("Placeholder \($0)")
}
}
}
Keep in mind that LazyVStack
is lazy and doesn't render all rows all the time. So they are very performant and suggested by Apple itself in WWDC 2020.
iOS 13
There is a UITableView
behind SwiftUI's List
for iOS. So to remove
Extra separators (below the list):
you need a tableFooterView
and to remove
All separators (including the actual ones):
you need separatorStyle
to be .none
init() {
// 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")
}
}
Solution 2
iOS 13 builds only
while this solution works correctly let's clean up the work using
ViewModifier
public struct ListSeparatorStyleNoneModifier: ViewModifier {
public func body(content: Content) -> some View {
content.onAppear {
UITableView.appearance().separatorStyle = .none
}.onDisappear {
UITableView.appearance().separatorStyle = .singleLine
}
}
}
now let's make a small extension that would help to hide the details
extension View {
public func listSeparatorStyleNone() -> some View {
modifier(ListSeparatorStyleNoneModifier())
}
}
As you can see, we’ve wrapped our appearance setting code into a neat little view modifier. you can declare it directly now
List {
Text("1")
Text("2")
Text("3")
}.listSeparatorStyleNone()
Solution 3
You may use ForEach
within a ScrollView
instead of List
for dynamic views without any styling
Solution 4
iOS 13 builds only:
The current workaround is to remove them via UIAppearance
:
UITableView.appearance(whenContainedInInstancesOf:
[UIHostingController<ContentView>.self]
).separatorStyle = .none
Solution 5
iOS 13 builds only:
See existing answers using UITableView.appearance()
.
⚠️ Be aware that in the iOS 14 SDK, List
does not appear to be backed by UITableView
. See the alternate solution below:
iOS 14 Xcode 12 Beta 1 only:
I do have a pure SwiftUI solution for iOS 14, but who knows how long it's going to continue working for. It relies on your content being the same size (or larger) than the default list row and having an opaque background.
⚠️ This does not work for iOS 13 builds.
Tested in Xcode 12 beta 1:
yourRowContent
.padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
.frame(
minWidth: 0, maxWidth: .infinity,
minHeight: 44,
alignment: .leading
)
.listRowInsets(EdgeInsets())
.background(Color.white)
Or if you're looking for a reusable ViewModifier
:
import SwiftUI
struct HideRowSeparatorModifier: ViewModifier {
static let defaultListRowHeight: CGFloat = 44
var insets: EdgeInsets
var background: Color
init(insets: EdgeInsets, background: Color) {
self.insets = insets
var alpha: CGFloat = 0
UIColor(background).getWhite(nil, alpha: &alpha)
assert(alpha == 1, "Setting background to a non-opaque color will result in separators remaining visible.")
self.background = background
}
func body(content: Content) -> some View {
content
.padding(insets)
.frame(
minWidth: 0, maxWidth: .infinity,
minHeight: Self.defaultListRowHeight,
alignment: .leading
)
.listRowInsets(EdgeInsets())
.background(background)
}
}
extension EdgeInsets {
static let defaultListRowInsets = Self(top: 0, leading: 16, bottom: 0, trailing: 16)
}
extension View {
func hideRowSeparator(
insets: EdgeInsets = .defaultListRowInsets,
background: Color = .white
) -> some View {
modifier(HideRowSeparatorModifier(
insets: insets,
background: background
))
}
}
struct HideRowSeparator_Previews: PreviewProvider {
static var previews: some View {
List {
ForEach(0..<10) { _ in
Text("Text")
.hideRowSeparator()
}
}
.previewLayout(.sizeThatFits)
}
}
Related videos on Youtube
Comments
-
Schiopu Evgheni almost 3 years
I'm trying to remove the "row" separators (known as dividers in SwiftUI) from a
List
in SwiftUI.I went through the
List
documentation, but I haven't been able to find a modifier for that.Any help would be appreciated.
-
Kuya about 5 yearsSimple rewording to make the post more understandable
-
VdeVentura about 5 yearsKuya's edit makes sense. I'm having the same issue which is how my search engine lead me here. The original author wants to remove the dividing lines that come by default with the
List
view. -
Mojtaba Hosseini almost 3 years@Schiopu Evgheni please mark an answer as accepted and don't let a question be open for years. Thanks
-
-
zerohedge about 5 yearsThis doesn't work if the
ScrollView
is inside aVStack
-
elight over 4 yearsGreat answer, gonna run with this!
-
Thanh-Nhon Nguyen about 4 yearsThis solution doesn't work when you have a 2nd list presented as sheet and you don't want to hide separator in that 2nd list.
-
BurgerZ about 4 yearsThis is correct answer for iOS 14. For iOS 13 builds answers with UITableView.appearance().separatorStyle = .none work fine.
-
Mojtaba Hosseini about 4 yearsIt's not removing the separator. It is just adding a
.background(Color.white)
on a view on top of the separator and blocks the view. try.background(Color.red.opacity(0.2))
to see yourself. -
sam-w about 4 years@MojtabaHosseini if you check out the code I posted, you'll see that I'm asserting exactly the same thing! Thanks so much for being so specific about the definition of
removing
! -
Reinhard Männer almost 4 yearsI tried your suggestion for iOS 14 with Xcode 12.0 beta 2 (ScrollView / LazyVStack), but it still shows the cell separators. Additionally, List still has the same separators.
-
Adrian Ciolea almost 4 yearsReplacing List with Scrollview with VStack messes with the NavigationView with large title
-
JAHelia almost 4 yearsthis solution still shows the separator on top of the first row in list
-
Wahab Khan Jadon over 3 yearsWorked on iOS14 but how to hide
>
this simbol at the end of row ... -
ChrisH over 3 yearsThis is asinine. Not your code - the NEED for that code. SwiftUI continues to be not ready for prime time. :(
-
ScottyBlades about 3 yearsThis doesn't lazy display like a list either.
-
Rico Crescenzio about 3 yearsUse a
LazyVStack
for lazy loading -
Karanveer Singh about 3 yearsApple really rushed SwiftUI by at least 2 years. So much stuff missing
-
Aaron Hayman almost 3 yearsThis works, but it's more like a "rowBackground" that covers the separator (and covers the
listRowBackground
if set). To handle anything over than a white row, I'd recommend renaming the extension torowBackground(color: _)
to allow setting the color. If you need to add a separator, you can then add it to view itself. -
XpressGeek over 2 yearsScrollView { LazyVStack { ForEach((1...100), id: \.self) { Text("Placeholder ($0)") } } } Its nicely done my job on iOS 14
-
Logan over 2 yearsthis should be the accepted answer! Also, I was able to just do
.listStyle(.sidebar)