I\'m trying to remove the "row" separators (known as dividers in SwiftUI) from a List
in SwiftUI.
I went through the List
document
The current workaround is to remove them via UIAppearance
:
UITableView.appearance(whenContainedInInstancesOf:
[UIHostingController<ContentView>.self]
).separatorStyle = .none
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.
There is a UITableView
behind SwiftUI's List
for iOS. So to remove
you need a tableFooterView
and to remove
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")
}
}
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:
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)
}
}
You may use ForEach
within a ScrollView
instead of List
for dynamic views without any styling
From: Swiftui Views Mastery Book SwiftUI 2.0 Mark Moeykens
.listStyle(SidebarListStyle()) # IOS 14
You can apply this new list style which will remove the separator lines.
Adding UITableView.appearance().separatorColor = .clear
for initializer
struct SomeView: View {
init() {
UITableView.appearance().separatorColor = .clear
}
}
I hope you to resolve this problem.