Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GeometryReader in SwiftUI ScrollView causes weird behaviour and random offset

Tags:

ios

swift

swiftui

Im trying to create a ScrollView that in turn contains a GeometryReader (Explicitly not the other way around). The GeometryReader should contain an (image) with a fixed width and height. However when doing this, the ScrollView pushes the view "above" the screen, it seems like it's applying some random vertical offset.

enter image description here

var body: some View {
    ScrollView {
        GeometryReader { geometry in
            Image("hp")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: geometry.size.width, height: 400)
                .clipped()
        }
    }
}

When removing the GeometryReader and just inserting the image it works fine.

Can somebody help?

Edit: Found a solution. I achieved the desired behaviour by telling the image that it should be as high and wide as the inner geometry reader. Then i'm setting the inner geometry reader's frame. I'm using an outer geometry reader for accessing the overall screen's dimensions

var body: some View {
    GeometryReader { outerGeometry in
        ScrollView {
            VStack {
                GeometryReader { innerGeometry in
                    Image("hp")
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(width: innerGeometry.size.width,
                        height: innerGeometry.size.height)
                        .offset(y: innerGeometry.frame(in: .global).minY/7)
                        .clipped()
                }
                    .frame(width: outerGeometry.size.width, height: 300)
            }
        }
    }
}

I hope it helps somebody!

like image 817
Andreas Schultz Avatar asked Nov 21 '19 00:11

Andreas Schultz


2 Answers

Just try to put ScrollView inside GeometryReader and not vice versa:

// ...
    var body: some View {
        
        GeometryReader { geometry in
            
            ScrollView {
                Image("hp")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: geometry.size.width, height: 400)
                    .clipped()
            }
        }
            
    }
// ...

and the result should be:

enter image description here

like image 160
Hrabovskyi Oleksandr Avatar answered Oct 19 '22 23:10

Hrabovskyi Oleksandr


GeometryReader, if placed as you did, provides the size not of ScrollView itself, but of "Content View" in which image is placed. "Content View" of ScrollView is bigger than screen size, to allow spring effect at the edges, when one scrolls more than a scrolling document size.

The correct usage is in @Александр_Грабовский's answer.

like image 26
Asperi Avatar answered Oct 20 '22 01:10

Asperi