GeometryReader

yongbeom kwak·2022년 8월 7일
0

GeometryReader

목록 보기
1/1

GeometryReader란?

GeometryReader는 그 자체로 View이며 상위뷰의 컨테이너의 크기를 통해서 하위뷰의 위치 및 크기를 선언하는데 사용한다.

GeometryProxy

container view의 크기 및 좌표공간에 대한 엑세스를 위한 proxy(대리인)이다.

속성

  • frame(in:): 특정좌표계를 기준으로 한 프레임 정보를 제공
  • size: geometry reader의 크기를 반환합니다
  • safeAreaInsets: geometry read가 사용된 환경에서의 안전영역에 대한 크기를 반환
  • subscript(anchor:): 자식 뷰에서 anchorePreference수식어를 이용해 제공한 좌표나 프레임을 geometry reader의 좌표계 기준으로 다시 변환하여 사용하는 서브스크립, 이때 Anchor의 제네릭 매개변수에는 CGRect 또는 CGPoint 타입 두 가지를 사용할 수 있습니다.

정리

GeometryReader로 뷰를 감싼 상위뷰 컨테이너의 frame,size,safeAreaInserts를 사용해서 하위뷰의 크기정보를 전달할 수 있다.

import SwiftUI

struct ContentView: View {
    var body: some View {
        // => iOS 14부터는 GeometryReader가 직접 안전 영역에 맞닿은 면에 한해 그 크기를 가져옵니다.
            // 즉, bottom 은 다른 뷰에 접해있고 top 만 안전 영역에 닿아 있다면 bottom 은 0이고 top 만 알맞은 값을 가집니다.
        VStack{
            GeometryReader { geomotry in
                
                Text("Geometry Reader")
                    .font(.largeTitle.bold())
                
                    .position(x: geomotry.size.width / 2, y: geomotry.safeAreaInsets.top) // 가로 중간 및 , 높이는 안전영역 위에
                
                
                VStack{
                    Text("Size").bold()
                    
                    Text("width : \(Int(geomotry.size.width))")
                    Text("Height : \(Int(geomotry.size.height))")
                }.position(x: geomotry.size.width/2, y: geomotry.size.height / 2.5)
                // VStack을 geomotry.size.width 중간에 위치 , y: geomory 높이/2.5에 위치
                
                VStack {
                    Text("SafeAreaInsets").bold()
                    // 🔥
                    Text("top : \(Int(geomotry.safeAreaInsets.top))")
                    Text("bottom : \(Int(geomotry.safeAreaInsets.bottom))")
                }
                // 🔥
                .position(x: geomotry.size.width / 2, y: geomotry.size.height / 1.4)
                // VStack을 geomotry.size.width 중간에 위치 , y: geomory 높이/1.4에 위치
                
                
            }
            .font(.title)
            .frame(height:500)
            .border(.green,width: 5)
        }
        
        Rectangle()
    }
}

결과

Frame

enum CoordinateSpace {
  case global                // 화면 전체 영역(window bounds)을 기준으로 한 좌표 정보
  case local                 // GeometryReader bounds 를 기준으로 한 좌표 정보
  case named(AnyHashable)    // 명시적으로 이름을 할당한 공간을 기준으로 한 좌표 정보
}    
import SwiftUI

struct FrameView: View {
    var body: some View {
        HStack {
            Rectangle().fill(Color.yellow)
                .frame(width: 30)

            VStack {
                Rectangle().fill(Color.blue)
                    .frame(height: 200)

                GeometryReader {
                    self.contents(geometry: $0)
                        .position(x: $0.size.width / 2, y: $0.size.height / 2) //상위 뷰인 VStack의 중간에 위치
                }
                .background(Color.green)
                .border(Color.red, width: 4)
            }
            .coordinateSpace(name: "VStackCS") //이름 부여
        }
        .coordinateSpace(name: "HStackCS") //이름 부여
    }

/// GeometryProxy.frame 다루기
    func contents(geometry g: GeometryProxy) -> some View {
        VStack {
            // 🔥 GeometryReader 자신에 대한 bounds 값을 반환.(그래서 원점 (0,0) 반환)
            Text("Local").bold()
            Text(stringFormat(for: g.frame(in: .local).origin))
                .padding(.bottom)

            // 🔥
            Text("Global").bold()
            Text(stringFormat(for: g.frame(in: .global).origin))
                .padding(.bottom)

            Text("Named VStackCS").bold()
            Text(stringFormat(for: g.frame(in: .named("VStackCS")).origin))
                .padding(.bottom)

            Text("Named HStackCS").bold()
            Text(stringFormat(for: g.frame(in: .named("HStackCS")).origin))
                .padding(.bottom)
        }
    }

/// CGPoint 를 가지고, String 으로 반환.
    func stringFormat(for point: CGPoint) -> String {
        String(format: "(x: %.f, y: %.f)", arguments: [point.x, point.y])
    }
}

결과

profile
IOS개발 공부생

0개의 댓글