Getting the view size dynamically in SwiftUI

To get the size of the view dynamically while the app is running in SwiftUI, use GeometryReader.

This article explains the specific method and code examples.

TOC

Outputs the view size into the console

To get the view size with GeometryReader, write as follows.

struct ContentView: View {

    var body: some View {
        Text("Hello, world!")
            .padding()
            .background() {
                GeometryReader { geometry in
                    Path { path in
                        print("Text frame size = \(geometry.size)")
                    }
                }
            }
    }
}

When this code is executed, the size of the Text is output to the console as follows.

Text frame size = (126.66666666666666, 52.33333333333333)

Place GeometryReader in the background

The view that can know its own size in SwiftUI is the GeometryReader. So, using the background modifier, place the GeometryReader in the view whose size you want to get.

geometry is a GeometryProxy structure; the GeomertyProxy.size property contains the size of the view.

You can also use overlay

You can use the overlay modifier instead of the background modifier to get the size in the same way. It is a good idea to use different modifiers depending on the situation.

Implementation example, Display on label

Let’s implement the code we actually used. Let’s implement the code to display the value in a separate Text instead of outputting it to the console. The code will look something like this.

struct ContentView: View {
    @State private var labelSize: CGSize = CGSize()

    var body: some View {
        VStack {
            Text("Hello, world!")
                .padding()
                .background() {
                    GeometryReader { geometry in
                        Path { path in
                            let size = geometry.size
                            DispatchQueue.main.async {
                                if self.labelSize != size {
                                    self.labelSize = size
                                }
                            }
                        }
                    }
            }
            
            Text("Label Size : \(String(format: "%.0f x %.0f", labelSize.width, labelSize.height))")
        }
    }
}

When this code is executed, two labels are displayed as follows, with the size of the upper label displayed on the lower label.

Example of displaying size on a label
Example of displaying size on a label

Cannot change view contents using size retrieved during view construction

In order to display the acquired size in Text, the acquired size is assigned to the labelSize property. Since we want to use this value to change the display content of Text, we add a @State attribute to let SwiftUI manage the labelSize.

It is important to note that the moment the view size is obtained by the GeometryReader, the view is still in the construction; if the labelSize property is changed, the view must be rebuilt. If the labelSize property is changed while the view is being rebuilt, it cannot be rebuilt, an error occurs, and the text cannot be displayed using the acquired value.

When I actually do this, it works in Xcode’s live preview, but when I run it in the iOS simulator or on an actual device, it does not show the size.

0 x 0 is displayed in the iOS simulator or on the actual device.
0 x 0 is displayed in the iOS simulator or on the actual device.

The following error message also appears in Xcode when run on an iOS simulator or actual device.

Error pointed out by Xcode
Error pointed out by Xcode

Modifying state during view update, this will cause undefined behavior.

Therefore, we use the DispatchQueue.main.async method to have the property assigned a value after the rebuilding process is complete. When the property is updated, the view is rebuilt.

Worked on iOS simulator and real devices.
Worked on iOS simulator and real devices
Let's share this post !

Author of this article

Akira Hayashiのアバター Akira Hayashi Representative, Software Engineer

I am an application developer loves programming. This blog is a tech blog, its articles are learning notes. In my work, I mainly focus on desktop and mobile application development, but I also write technical books and teach seminars. The websites of my work and books are here -> RK Kaihatsu.

TOC