RealUglyDuck
RealUglyDuck

Reputation: 377

SwiftUI List add empty space at the bottom

I would like to allow the SwiftUI List to scroll all the way up to the place where header of the last Section will be at the top of the List view. I know that I could use GeometryReader to calculate height of the List and by knowing the height of each list cell I could calculate how much empty space I should add at the bottom of the list to push it up. The problem is that if cells will for example expand or have flexible size, then it won't work. I was wondering if there is maybe some modifier that I don't know about or some more "flexible" way to do that?

This is the code for the List

import SwiftUI

struct ListSections: View {
    var body: some View {
        List {
            Section(header: Text("Header 1")) {
                ForEach((0...10), id: \.self) { index in
                    Text("item \(index)")
                }
            }
            
            Section(header: Text("Header 2")) {
                ForEach((0...12), id: \.self) { index in
                    Text("item \(index)")
                }
            }
        }
    }
}

On the image below you can see on the left how far I can scroll by default and on the right how far I would like to be able to scroll.

enter image description here

Upvotes: 5

Views: 4023

Answers (4)

Lucas
Lucas

Reputation: 6729

From iOS 17 on we can use contentMargins

    List {

    }
    .contentMargins(.bottom, 100, for: .scrollContent)

Upvotes: -2

Kjuly
Kjuly

Reputation: 35131

Complement to the accepted answer, we can also add an empty footer to the last section:

List {
  Section {
    ForEach((0...12), id: \.self) { index in
      Text("item \(index)")
    }

  } header: {
    Text("Header 2")

  } footer: {
    Spacer()
      .frame(height: 300)
      .listSectionSeparator(.hidden)
  }
}

Upvotes: 0

Eido 9oya
Eido 9oya

Reputation: 59

In iOS 17, the safeAreaPadding(_:) allows you to add contentsInsets to the edges of the view. To implement this in your code, you can follow these steps:

import SwiftUI

struct ListSections: View {
    var body: some View {
        List {
            Section(header: Text("Header 1")) {
                ForEach((0...10), id: \.self) { index in
                    Text("item \(index)")
                }
            }

            Section(header: Text("Header 2")) {
                ForEach((0...12), id: \.self) { index in
                    Text("item \(index)")
                }
            }
        }
        .safeAreaPadding(EdgeInsets(top: 0, leading: 0, bottom: 100, trailing: 0))
    }
}

Upvotes: 5

kstefanou
kstefanou

Reputation: 617

There are two options here: Option 1 (preferred way) Just adding a bottom padding to the last Section:

struct ListSections: View {
    var body: some View {
        List {
            Section(header: Text("Header 1")) {
                ForEach((0...10), id: \.self) { index in
                    Text("item \(index)")
                }
            }

            Section(header: Text("Header 2")) {
                ForEach((0...12), id: \.self) { index in
                    Text("item \(index)")
                }
            }
            .padding(.bottom, 300)
        }
    }
}

Option 2: Adding a View after the last section inside your List will do the trick. For instance I used a Color view.

Your code should look like:

struct ListSections: View {
    var body: some View {
        List {
            Section(header: Text("Header 1")) {
                ForEach((0...10), id: \.self) { index in
                    Text("item \(index)")
                }
            }
            
            Section(header: Text("Header 2")) {
                ForEach((0...12), id: \.self) { index in
                    Text("item \(index)")
                }
            }
            
            Color(.clear)
               .frame(height: 300)
        }
    }
}

Upvotes: 5

Related Questions