Kishore Suthar
Kishore Suthar

Reputation: 2983

List hides when adding in ScrollView SwiftUI

I have added a List inside the ScorllView but it's not showing in canvas after adding inside to ScrollView

here is my code

struct ContentView: View {
    var body: some View {
        ScrollView {
            VStack {
                Text("My List")
                    .font(.largeTitle)
                    .fontWeight(.bold)

                List(0 ..< 5) { item in
                    Text("Hello World")
                }
            }
        }
    }
}

sw

Upvotes: 16

Views: 5047

Answers (3)

Asperi
Asperi

Reputation: 257493

I assume you expected the following:

var body: some View {
    GeometryReader { geometry in
        ScrollView {
           VStack {
               Text("My List")
                   .font(.largeTitle)
                   .fontWeight(.bold)

                List {
                    ForEach(0 ..< 50) { item in // 50 for testing
                        Text("Hello World")
                    }
                }
            }
            .frame(height: geometry.size.height)
        }
    }
}

Upvotes: 9

Vil&#233;m Kurz
Vil&#233;m Kurz

Reputation: 3400

There are many reasons, why you might need a List in a ScrollView. Mine is, that I have a form, where one of the rows is a grid of images, each with a contextMenu. ContextMenu does not work in a List Row with grid content. So, this row can not be in a List. And I have other rows, where I need swipe actions. Which do not work outside of the List. That's why I have to use a List, within a ScrollView. Combining these responses https://stackoverflow.com/a/68789867/1379833, https://stackoverflow.com/a/60758138/1379833 with GeometryReader I got it to work.

import Introspect

@State private var tableViewContentHeight: CGFloat = 0

var body: some View {
    GeometryReader { screenGeometryReader in
        ScrollView {
            ... // content of the scrollView
            List {
                ... // content of the list
            }
            .introspectTableView { tableView in
                tableViewContentHeight = tableView.contentSize.height
            }
            .frame(
                width: screenGeometryReader.size.width, 
                height: tableViewContentHeight
            )
        }
    }
}

Upvotes: 1

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119128

The Issue:

That is because List infer it size from its parent View. So when you embed it inside something like VStack that have dynamic height, it can't infer it size correctly.

Solutions:

You have some options here:

1. Size List to match it's content Automatically (Perfect)

You can use ForEach directly instead of using List, then you have more control over the content size

ForEach(0 ..< 5) { item in
    VStack(alignment: .leading) {
        Text("Hello World").frame(height: 42)
        Divider()
    }.padding(.horizontal, 8)
}

You can change all sizes and spacings according to your needs


2. Size List to match it's content manually (Good but not perfect)

Give it a static frame like the way you do in UIKit by setting the .frame() modifier on the List:

List(0 ..< 5) { item in
    Text("Hello World")
}.frame(height: 224)

You can use GeometryReader to find the exact size of the parent and apply it to the List


3. Just show the List (Not good but it works)

add .scaledToFill() modifier to List

Upvotes: 25

Related Questions