shinhong
shinhong

Reputation: 446

How to make an item in ScrollView take up the height of the entire screen in SwiftUI?

I'm developing an watchOS app using SwiftUI. It's my first time using SwiftUI and developing an watchOS app.

I want to create a ScrollView which contains 2 Views, each of which should have the same height as the entire screen.

import SwiftUI

struct ScrollViewContainer_swift: View {
    var body: some View {
        ScrollView {
            DetailView()
            DetailView()
        }
    }
}

struct ScrollViewContainer_swift_Previews: PreviewProvider {
    static var previews: some View {
        ScrollViewContainer_swift()
    }
}
import SwiftUI

struct DetailView: View {
    var body: some View {
        VStack {
            Spacer()
            Text("This should take up the height of the entire screen.")
            Spacer()
        }
        .ignoresSafeArea(.container, edges: .all)
        .background(Color.blue)
    }
}

struct DetailView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView()
    }
}

Using ignoresSafeArea, I could make a single DetailView to take up the full height. The result of DetailView_Previews looks like this:

enter image description here

However, if I put it into the ScrollView, the DetailViews seem to shrink to the minimum height:

enter image description here

I have tried the followings, but none of these seemed to do the trick.

Forcing the height of the view like DetailView().frame(height: 170) did similar to what I want to achieve, but it obviously cannot adapt to various screen sizes.

Is there anything else I can try?

Thank you.

Upvotes: 1

Views: 5620

Answers (2)

laka
laka

Reputation: 796

GeometryReader has it's place but for what was asked here, it's most probably the wrong tool. Regarding GeometryReader there are at least two things to consider:

  1. It can have performance drawbacks
  2. It might alter your layout. Eventually you can get into other issues depending on how the view is build up and how SwiftUI refreshes the view

For aligning heights of elements you most probably can achieve it with a combination of .fixedSize(horizontal: false, vertical: true) on the container and .frame(maxHeight: .infinity) on the element's itself.

Here is a pretty small example:

HStack {
    VStack {
        Text("We")
        Text("don't")
        Text("need")
        Text("GeometryReader")
    }
    .background(Color.blue)
    .frame(maxHeight: .infinity)

    Text("Only One Line")
        .frame(maxHeight: .infinity)
        .background(Color.green)
}
.fixedSize(horizontal: false, vertical: true)

Screenshot of resulting view of the code above

Further reading:

Upvotes: -1

jnpdx
jnpdx

Reputation: 52347

In your current code, the ScrollView will take up all available space in one screen. Then, the DetailView will only take up as much space as it needs. Even with the Spacers, it won't expand vertically because the ScrollView isn't imposing a size constraint on it.

In order to get the DetailViews to be the size of the screen, you can use a GeometryReader and then pass down the height to the child views:

struct ContentView : View {
    var body: some View {
        GeometryReader { proxy in
            ScrollView {
                VStack(spacing: 0) {
                    DetailView().frame(height: proxy.size.height)
                    DetailView().frame(height: proxy.size.height)
                }
            }
        }.ignoresSafeArea()
    }
}

struct DetailView: View {
    var body: some View {
        VStack {
            Spacer()
            Text("This should take up the height of the entire screen.")
            Spacer()
        }
        //.frame(maxWidth: .infinity) //add this if you want the view to extend to the horizontal edges
        .background(Color.blue)
    }
}

Upvotes: 2

Related Questions