How to use geometry reader so that the view does not expand?

Viewed 1138

I have used geometry reader like this

GeometryReader { r in
   ScrollView {
      Text("SomeText").frame(width: r.size.width / 2)
   }
}

The problem is that the reader expands vertically much like Spacer(). Is there anyway that I can make it not do this?

3 Answers

After googling around I found this answer here.

Create this new struct

struct SingleAxisGeometryReader<Content: View>: View {
    private struct SizeKey: PreferenceKey {
        static var defaultValue: CGFloat { 10 }
        static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
            value = max(value, nextValue())
        }
    }

    @State private var size: CGFloat = SizeKey.defaultValue
    var axis: Axis = .horizontal
    var alignment: Alignment = .center
    let content: (CGFloat)->Content

    var body: some View {
        content(size)
            .frame(maxWidth:  axis == .horizontal ? .infinity : nil,
                   maxHeight: axis == .vertical   ? .infinity : nil,
                   alignment: alignment)
            .background(GeometryReader {
                proxy in
                Color.clear.preference(key: SizeKey.self, value: axis == .horizontal ? proxy.size.width : proxy.size.height)
            }).onPreferenceChange(SizeKey.self) { size = $0 }
    }
}

And then use it like this

SingleAxisGeometryReader { width in  // For horizontal
   // stuff here
}

or

SingleAxisGeometryReader(axis: .vertical) { height in  // For vertical
   // stuff here
}

With this answer, it’s now generic with no code change.

Since background is fit to actual view size always.you can use this trick, adding GeometryReader in background without changing the size of the view itself.

       ScrollView {
        
    }.background(
        GeometryReader { r in
            // stuff
        }
    )
}

It's somewhat unclear what you're actually trying to do with the views if it's not actually the code you gave at the top. With regards to that, though, you can swap the position of the GeometryReader and the ScrollView. What the GeometryReader does is find the frame of the available space, and it fills it. With a ScrollView the actual height is 0. So, this:

ScrollView {
       GeometryReader {r in
          Text("SomeText").frame(width: r.size.width / 2)
       }
    }
Related