GeometryReader

https://www.hackingwithswift.com/quick-start/swiftui/how-to-provide-relative-sizes-using-geometryreader

GeometryReader to the Rescue

What the Parent Wants

When coding your custom view, you often do not need to worry about surroundings or sizing. For example, if you need to create a view that draws a rectangle, you just draw a rectangle. It will be drawn with the size and position intended by the parent.

In the following example, we have a VStack with a size of 150×100. It first puts the Text on the top and then the remaining space is passed to MyRectangle(). This view is very obedient and paints in blue exactly what has been given. Not a pixel more, not a pixel less:

Blue MyRectangle()
struct ContentView : View {
    var body: some View {
        
        VStack {
            
            Text("Hello There!")
            MyRectangle()
            
        }.frame(width: 150, height: 100).border(Color.black)

    }
}

struct MyRectangle: View {
    var body: some View {
        Rectangle().fill(Color.blue)
    }
}

As you can see, the view MyRectangle() does not worry about size. It only does one job, draw a rectangle. Let SwiftUI figure out where and how big the parent wants it. In this case, the containing VStack is such parent.

If you would like to learn more about how parents determine size and position for their children, I strongly suggest you watch the 2019 WWDC session 237 (Building Custom Views with SwiftUI).

In many cases, this would be enough. However, as explained on session 237, parents suggest a size and position, but it is up to the child view to decide where and how to draw itself. If the child view is not happy with what its was offered, then he can just ignore it.

For example, if you want your custom view to draw a rectangle with half the size of the one suggested by your parent, and if you want to positioned it 5 points to the right edge of the suggested location, then so be it. Nobody will tell you otherwise.

So how do we go off script here? It turns out, is not that complicated. Here is where GeometryReader comes to the rescue.

What the Child Does

A container view that defines its content as a function of its own size and coordinate space.

Comparing to other entries that only say “No overview available”, we can consider ourselves lucky!

But what does this mean anyway? Well basically, GeometryReader is yet another view! Surprised? I guess you’re not by now. Almost everything is a view with SwiftUI! As you will see in the example below, GeometryReader lets YOU define its contents, but unlike other views, you also have access to some useful information you can seize to do your thing in the process.

Consider the exercise we mentioned before: Make a view that draws a rectangle with half the size of the parent’s suggestion and positions it 5 points to the right side of the suggested area. Now that we have GeometryReader, it is very simple:

Red MyRectangle()
struct ContentView : View {
    var body: some View {
        
        VStack {
            
            Text("Hello There!")
            MyRectangle()
            
        }.frame(width: 150, height: 100).border(Color.black)

    }
}

struct MyRectangle: View {
    var body: some View {
        GeometryReader { geometry in
            Rectangle()
                .path(in: CGRect(x: geometry.size.width + 5,
                                 y: 0,
                                 width: geometry.size.width / 2.0,
                                 height: geometry.size.height / 2.0))
                .fill(Color.blue)
            
        }
    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s