SwiftUI: GeometryReader
GeometryReader 부모 뷰의 크기 및 좌표 시스템을 활용하여 하위 뷰의 레이아웃과 위치를 제어할 수 있는 컨테이너 뷰 UIScreen UIScreen을 활용하여 화면의 너비에 따라 레이아웃이나 위치를 지정할 수 있지만, Landscape모드 등 유동적으로 적
GeometryReader
- 상위 뷰의 크기 및 좌표 시스템을 활용하여 하위 뷰의 레이아웃과 위치를 제어할 수 있는 컨테이너 뷰
UIScreen
UIScreen을 활용하여 화면의 너비에 따라 레이아웃이나 위치를 지정할 수 있다.- 모든 상황에서 화면의 너비를 기준으로 하기 때문에
Landscape모드 등 유동적으로 적용되지 않는다.
HStack(spacing: 0) {
Rectangle()
.fill(.red)
// 화면 너비의 3/2 크기
.frame(width: UIScreen.main.bounds.width * 0.666)
Rectangle()
.fill(.blue)
}
.ignoresSafeArea()

GeometryReader
- 상위 뷰의 주어진 공간 내에서 하위 뷰의 위치와 크기를 유동적으로 결정할 수 있다.
- 클로저 내에서
GeometryProxy를 통해 상위 뷰 정보에 접근할 수 있다. GeometryReader는 리소스를 많이 차지하기 때문에 남용하지 말고 꼭 필요한 상황에서만 사용해야한다.
GeometryReader { geometry in
HStack(spacing: 0) {
Rectangle()
.fill(.red)
// 상위 뷰 너비의 3/2 크기
.frame(width: geometry.size.width * 0.666)
Rectangle()
.fill(.blue)
}
.ignoresSafeArea()
}

GeometryReader Frame
frmae(in:)을 통해 특정 좌표계를 기준으로 한 프레임 정보를 가저올 수 있다.
enum CoordinateSpace {
case global // 화면 전체 영역 기준
case local // GeometryReader 기준
case named(AnyHashable) // 명시적으로 이름을 할당한 공간 기준
}

GeometryReader를 활용하여 다양한 특수효과를 표현할 수 있다.
struct GeometryReaderStudy: View {
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<20) { index in
GeometryReader { geometry in
RoundedRectangle(cornerRadius: 20)
.rotation3DEffect(
// 카드의 현재 위치에 따라 각도를 다르게 조절
Angle(degrees: getPercentage(geo: geometry)) * 20,
axis: (x: 0.0, y: 1.0, z: 0.0))
}
.frame(width: 300, height: 250)
.padding()
}
}
}
}
func getPercentage(geo: GeometryProxy) -> Double {
// 화면의 중앙 위치
let maxDistance = UIScreen.main.bounds.width / 2
// 화면 전체 영역 기준 카드의 현재 중앙 좌표
let currentX = geo.frame(in: .global).midX
// 두 위치에 대한 비율 계산
return Double(1 - (currentX / maxDistance))
}
}
