SwiftUI: GeometryReader

Snack 남관식·2023년 5월 27일
0

SwiftUI

목록 보기
27/35
post-thumbnail
post-custom-banner

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))
    }
}

profile
iOS Developer | Product Designer @snacknam
post-custom-banner

0개의 댓글