본문 바로가기

iOS/SwiftUI

SwiftUI - GeometryReader, CoordinateSpace

GeometryReader

https://developer.apple.com/documentation/swiftui/geometryreader

 

GeometryReader | Apple Developer Documentation

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

developer.apple.com

 

GeometryReader는 자신의 크기와 좌표 공간을 함수로 사용여 컨텐츠를 정의하는 컨테이너 뷰다.

 

이를 통해 자신이 배치된 부모 뷰의 크기와 좌표 공간에 대한 정보를 얻을 수 있고,

이 정보를 기반으로 레이아웃을 동적으로 정의할 수 있다.

 

import SwiftUI

struct ContentView: View {
    var body: some View {
        GeometryReader { proxy in
            VStack(spacing: 50) {
                Text("Width: \(proxy.size.width)")
                    .frame(width: proxy.size.width)
                    .border(.red)
                
                Text("Height: \(proxy.size.height / 10)")
                    .frame(height: proxy.size.height / 10)
                    .border(.red)
                
                Text("X: \(proxy.frame(in: .local).minX)")
                
                Text("Y: \(proxy.frame(in: .local).minY)")
            }
            .frame(
                width: proxy.size.width,
                height: proxy.size.height
            )
        }
    }
}

 

 

GeometryReader를 사용하여 뷰를 그릴 때 다음의 스텝을 거치게 된다.

 

1. 부모가 자식에게 크기 제안

부모 뷰가 자식 뷰에게 크기를 제안한다. 이 크기는 부모의 레이아웃 요구사항을 반영한 것이다. (frame 모디파이어 등)

 

2. 자식은 자신의 크기 결정

자식 뷰는 부모로부터 받은 크기 제안을 바탕으로 자자신의 크기를 결정한다. 이 과정에서 자식 뷰는 필요에 따라 부모가 제안한 크기를 무시하고 자신이 필요로 하는 크기를 반환할 수 있다.

 

3. 부모가 자식을 포지셔닝

부모 뷰는 자식 뷰가 결정한 크기를 사용하여 자식 뷰를 적절하게 배치한다.

 

[주의]

 

GeometryReader는 가능한 모든 공간을 사용하려는 Greedy한 속성을 갖고 있다. 이 때문에 종종 자식 뷰가 예상보다 큰 크기를 가질 수 있는데, 이를 방지하려면 frame 모디파이러를 사용하여 크기를 제한해야 한다.

 

GeometryReaderd의 Greedy한 속성을 확인해보자.

import SwiftUI

struct GreedyGeometryReaderExample: View {
    var body: some View {
        VStack {
            Text("평범 텍스트")
                .background(Color.green)
            
            GeometryReader { proxy in
                Text("GeometryReader 안의 텍스트")
                    .frame(width: proxy.size.width)
                    .background(Color.blue)
            }
            .background(
                Color.red
                    .overlay(Text("공간을 다 먹어버림"))
            )
            
            Text("평범 텍스트")
                .background(Color.yellow)
        }
        .background(Color.gray)
    }
}

#Preview {
    GreedyGeometryReaderExample()
}

 

 

 

GeomentryProxy

GeometryReader에서 전달되는 `proxy` 매개변수는 GeomentryProxy 라는 타입의 인스턴스다.

이 GeomentryProxy는 아래 정보들을 제공한다.

 

1. 부모 뷰로부터 제안된 크기

 

부모 뷰가 자식 뷰에게 제안한 크기 반환

let proposedWidth = proxy.size.width
let proposedHeight = proxy.size.height

 

2. 적용된 safe area inset

 

부모 뷰로부터 적용된 safeareainset 값 반환

let safeAreaInsets = proxy.safeAreaInsets
let topInset = safeAreaInsets.top
let bottomInset = safeAreaInsets.bottom

 

3. frame 값을 읽을 수 있는 메서드

 

특정 좌표 공간 내에서 뷰의 프레임 값을 읽어 반환

어떤 좌표 공간에서 프레임 값을 읽을 것인지 명확히 지정

let localFrame = proxy.frame(in: .local)
let globalFrame = proxy.frame(in: .global)
let specificLayerFrame = proxy.frame(in: .named("layer"))

 

 

CoordinateSpace

 

CoordinateSpace의 정의와 static 프로퍼티에 대해 알아보자


https://developer.apple.com/documentation/swiftui/coordinatespace

 

CoordinateSpace | Apple Developer Documentation

A resolved coordinate space created by the coordinate space protocol.

developer.apple.com

 

A resolved coordinate space created by the coordinate space protocol.

Coordinatoe Space 프로토콜에 의해 해석되어 생성된 좌표 공간.

 

CoordinatoeSpace를 직접 사용하는 경우는 드물다.

대신 .global, local, .named(_:)와 같은 CoordinateSpaceProtocol의 static 프로퍼티와 함수를 사용하는 것이 좋다.

 

1. .global : 전체 화면 또는 앱의 좌표계

 

뷰의 프레임을 화면 전체를 기준으로 측정한다. 이 경우 X와 Y 좌표는 화면의 좌측 상단이 (0, 0)으로 설정된다.

 

2. .local: 현재 뷰의 좌표계

 

뷰의 부모 뷰를 기준으로 프레임을 측정한다. 이 경우 부모 뷰의 좌측 상단이 (0, 0)으로 설정된다.

 

3. .named(_:): 특정 이름으로 지정된 커스텀 좌표계 참조

 

커스텀 좌표 공간을 지정할 수 있다. coordinatoeSpace() 모디파이어를 사용하여 뷰에 특정 좌표 공간 이름을 부여할 수 있다.

그런 다음 해당 뷰의 자식 뷰들은 그 좌표 공간을 기준으로 프레임을 측정할 수 있다.

 

참고

 

https://www.hackingwithswift.com/books/ios-swiftui/understanding-frames-and-coordinates-inside-geometryreader

 

Understanding frames and coordinates inside GeometryReader - a free Hacking with iOS: SwiftUI Edition tutorial

Was this page useful? Let us know! 1 2 3 4 5

www.hackingwithswift.com