Swiftui - Using Geometryreader Without Modifying the View Size

SwiftUI - Using GeometryReader Without Modifying The View Size

I managed to solve this by wrapping the page main view inside a GeometryReader and pass down the safeAreaInsets to MyView. Since it is the main page view where we want the entire screen thus it is ok to be as greedy as possible.

Use SwiftUI GeometryReader without affecting outer frame?

Just add the .fixedSize() modifier to your HStack. That will achieve the desired affect.

SwiftUI - How to get GeometryReader size/height from different View?

You can:

  1. Make a @State property to store the height
  2. Set it using an .onAppear { attached to Color.clear
  3. Replace ??? with \(textHeight)
struct ContentView: View {
@State var textHeight = CGFloat(0) /// 1.

var body: some View {
VStack {
Text("Hello world!")
.background(
GeometryReader { proxy in
Color.clear
.onAppear { /// 2.
textHeight = proxy.size.height
}
}
)
/// 3.
Text("Height of first text is \(textHeight)")
}
}
}

Result:

"Hello world!" above "Height of first text is 20.333333"

SwiftUI: How to calculate a view's size based on it's frame's size without using a Geometry Reader?

The GeometryReader is exact instrument to read views geometry, actually. You just need to use it in different way (so not affect external layout).

Here is a solution that do not break layout. Tested with Xcode 12.1 / iOS 14.1

RoundedRectangle(cornerRadius: 12.0) // << this consumes available width only
.fill(Color(.lightGray))
.opacity(0.1)
.frame(height: 20)
.overlay(GeometryReader { geometry in // << this reads parent rectangle area
RoundedRectangle(cornerRadius: 12.0)
.fill(getColorForBar(progress: progress))
.frame(width: getFillWidth(progress: progress, geometry: geometry), height: 20)
.animation(self.progressAnimation)
}, alignment: .leading)

SwiftUI GeometryReader compact size

Here is possible approach. Tested with Xcode 11.4 / iOS 13.4 (w/ ContentView unchanged)

demo

struct LoadingTitle: View {

var body: some View {
VStack { Color.clear }
.frame(height: 22).frame(maxWidth: .infinity)
.padding(.vertical, 20)
.overlay(
GeometryReader { geo in
HStack {
HStack {
Color.gray
.frame(width: geo.size.width * 0.7, height: 22)
}
.padding(.vertical, 20)
.border(Color.gray, width: 1)
Spacer()
}
}
)
}
}

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

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.



Related Topics



Leave a reply



Submit