How to use GeometryReader in SwiftUI

Issue #735

From my previous post How to use flexible frame in SwiftUI we know that certain views have different frame behaviors. 2 of them are .overlay and GeometryReader that takes up whole size proposed by parent.

By default GeometryReader takes up whole width and height of parent, and align its content as .topLeading

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
VStack {
Rectangle()
.fill(Color.gray)
.overlay(
GeometryReader { geo in
Text("\(Int(geo.size.width))x\(Int(geo.size.height))")
.bold()
}
)
}
.frame(width: 300, height: 300)
}
}
Screenshot 2021-01-02 at 00 37 17

To align content center, we can specify frame with geo information

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
VStack {
Rectangle()
.fill(Color.gray)
.overlay(
GeometryReader { geo in
Text("\(Int(geo.size.width))x\(Int(geo.size.height))")
.bold()
.frame(width: geo.size.width, height: geo.size.height, alignment: .center)
}
)
}
.frame(width: 300, height: 300)
}
}

The result is that Text is center aligned

Screenshot 2021-01-02 at 00 39 13

If we were to implement GeometryReader, it would look like this

1
2
3
4
5
6
7
8
9
10
11
12
13
struct GeometryReader<Content: View>: View {
let content: (CGSize) -> Content

func size(proposedSize: CGSize) -> CGSize {
// Take up whole size proposed by parent
proposedSize
}

func buildBody(calculatedSize: CGSize) -> some View {
// Pass in the calculated size
content(calculatedSize)
}
}

Updated at 2021-01-01 23:42:34

Comments