How to Remove the Left and Right Padding of a List in Swiftui

How to remove the left and right Padding of a List in SwiftUI?

It looks like .listRowInsets doesn't work for rows in a List that is initialised with content.

So this doesn't work:

List(items) { item in
ItemRow(item: item)
.listRowInsets(EdgeInsets())
}

But this does:

List {
ForEach(items) { item in
ItemRow(item: item)
.listRowInsets(EdgeInsets())
}
}

Remove top padding from `List` in SwiftUI

Firstly, I would say that GroupedListStyle is working as intended.

On iOS, the grouped list style displays a larger header and footer
than the plain style, which visually distances the members of
different sections.

You say you have tried this, but it does work for me (Xcode 12.5.1):

    List { ... }    
.onAppear(perform: {
UITableView.appearance().contentInset.top = -35
})

You could also hide the list header, by using a ZStack with the List at the bottom of the stack and the Picker over the top. The Picker does have transparency, so you would also have to add an opaque view to act as background for the Picker.

var body: some View {
NavigationView {
ZStack(alignment: .top) {
List { ... }
.listStyle(.grouped)
.padding(.top, 30)

Color.white
.frame(height: 65)

Picker { ... }
.pickerStyle(.segmented)
.padding()
}
.navigationBarTitle("Add Task", displayMode: .inline)
}
}

Sample Image

As far as I can see this just appears the same as PlainListStyle would do, but I assume you have a particular reason for wanting to use GroupedListStyle.

Remove default padding from List in SwiftUI

To achieve this you need to use ForEach inside List combined with .listRowInsets as in example below

demo

struct Demo: View {
var colors: [Color] = [.red, .blue, .yellow]
var body: some View {
List {
ForEach(colors, id: \.self) { color in
color
}.listRowInsets(EdgeInsets())
}
// Update: Different iOS versions have different
// default List styles, so set explicit one if needed
.listStyle(PlainListStyle())
}
}

backup

SwiftUI: remove the space on List view left and right?

So, I finally found a built in way of doing this without having to hard code numbers. I spent some time digging around the documentation and found this, listRowInsets:

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension View {

/// Applies an inset to the rows in a list.
///
/// Use `listRowInsets(_:)` to change the default padding of the content of
/// list items.
///
/// In the example below, the `Flavor` enumeration provides content for list
/// items. The SwiftUI ``ForEach`` structure computes views for each element
/// of the `Flavor` enumeration and extracts the raw value of each of its
/// elements using the resulting text to create each list row item. The
/// `listRowInsets(_:)` modifier then changes the edge insets of each row
/// of the list according to the ``EdgeInsets`` provided:
///
/// struct ContentView: View {
/// enum Flavor: String, CaseIterable, Identifiable {
/// var id: String { self.rawValue }
/// case vanilla, chocolate, strawberry
/// }
///
/// var body: some View {
/// List {
/// ForEach(Flavor.allCases) {
/// Text($0.rawValue)
/// .listRowInsets(.init(top: 0,
/// leading: 25,
/// bottom: 0,
/// trailing: 0))
/// }
/// }
/// }
/// }
///
/// ![A screenshot showing a list with leading 25 point inset on each
/// row_x0013_.](SwiftUI-View-ListRowInsets.png)
///
/// - Parameter insets: The ``EdgeInsets`` to apply to the edges of the
/// view.
/// - Returns: A view that uses the given edge insets when used as a list
/// cell.
@inlinable public func listRowInsets(_ insets: EdgeInsets?) -> some View

}

So then changing my code to this:

var body: some View {

NavigationView {
List {
ForEach(sctions) { section in

Section(header: Text(section.name)
.border(Color(.red))
.listRowInsets(.init(top: 0,
leading: 0,
bottom: 0,
trailing: 0))) {

ForEach(section.items) { item in
Text("\(item.name)")
.listRowInsets(.init(top: 0,
leading: 0,
bottom: 0,
trailing: 0))
.border(Color(.green))
}

}
}

}
.listStyle(.plain)
.navigationBarTitle("Title")
}
}

Gives me this result:

Sample Image

Interestingly enough, listRowInsets works on the "cell", but also on the section header, which I then got stuck on. I wanted the section header to also go to the edges and it was not originally.

Hope this helps somebody else.

Left and right padding (not leading and trailing) in SwiftUI

Use @Environment(\.layoutDirection) to get the current layout direction (LTR or RTL) and use it to flip .leading and .trailing as needed.

Here’s a ViewModifier that wraps all that conveniently:

enum NoFlipEdge {
case left, right
}

struct NoFlipPadding: ViewModifier {
let edge: NoFlipEdge
let length: CGFloat?
@Environment(\.layoutDirection) var layoutDirection

private var computedEdge: Edge.Set {
if layoutDirection == .rightToLeft {
return edge == .left ? .trailing : .leading
} else {
return edge == .left ? .leading : .trailing
}
}

func body(content: Content) -> some View {
content
.padding(computedEdge, length)
}
}

extension View {
func padding(_ edge: NoFlipEdge, _ length: CGFloat? = nil) -> some View {
self.modifier(NoFlipPadding(edge: edge, length: length))
}
}

Use it like you would the standard padding modifiers:

Text("Text")
.padding(.left, 10)


Related Topics



Leave a reply



Submit