Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove top padding from `List` in SwiftUI

I've seen similar questions like this one here on Stack Overflow, but none of them have been able to answer my question.

I have created a List, but I want to remove the padding space (marked with a red arrow) above the content in the List. How can I remove it when using a GroupedListStyle?

Screenshot

This is a List within a VStack within a NavigationView that is displayed via fullscreenCover:

var body: some View {
  NavigationView {
    VStack {
      taskEventPicker
      myList
    }
    .navigationBarTitle("Add Task", displayMode: .inline)
  }
}

where taskEventPicker is a segmented Picker (boxed in green):

var taskEventPicker: some View {
  Picker("Mode", selection: $selection) { /* ... */ }
  .pickerStyle(SegmentedPickerStyle())
  .padding()
}

and myList is the form in question (boxed in yellow):

var myList: some View {
  List { /* ... */ }
  .listStyle(GroupedListStyle())
}

What I've Tried

  • Removing the header of the list
  • Hiding the Navigation Bar title
  • Setting UITableView.appearance().tableHeaderView to an empty frame
  • Attempting UITableView.appearance().contentInset.top = -35
  • Setting listRowInsets (this affects all list rows)

Note: I'm looking for an answer that can apply to the GroupedListStyle. I understand that this issue does not occur with PlainListStyle. This padding issue also occurs with the default listStyle.

Thanks for the help!

Xcode version: 12.5

like image 630
Ben Myers Avatar asked Jun 23 '21 03:06

Ben Myers


2 Answers

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)
    }
}

enter image description here

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.

like image 87
rbaldwin Avatar answered Oct 12 '22 13:10

rbaldwin


Give a header to the first section in your list: Section(header: Spacer(minLength: 0))

Disclaimer: this doesn't totally remove the top spacing, but it does yield the same result as the native Settings app.

Note: This worked for me on iOS 14.5

VStack {
    List {
        Section(header: Spacer(minLength: 0)) {
            Text(verbatim: "First Section")
        }

        Section {
            Text(verbatim: "Second Section")
        }
    }
    .listStyle(GroupedListStyle())
}

Without Section Header With Section Header Native Settings App

like image 37
SlimeBaron Avatar answered Oct 12 '22 14:10

SlimeBaron