UI를 작업하다보면 상대적 크기를 사용해야 하는 경우가 많이 발생한다.
예를들어, 부모뷰의 크기가 300x300 일때 자식뷰의 크기는 가로크기 동일, 세로크기는 1/3 크기(300x100) 와 같은 식이다.
이런 작업을 진행하려면 결국 상위뷰의 크기를 알아야하는데 각 컴포넌트의 사이즈 값에 접근할 길이 없다. Swift UI 에서는 이런 케이스를 위해 GeometryReader
라는것을 지원한다.
A container view that defines its content as a function of its own size and coordinate space.
콘텐츠를 자체 크기 및 좌표 공간의 함수로 정의하는 컨테이너 보기입니다.
흠... 무슨말인지 모르겠다. 코드로 살펴보자.
struct ImageScrollBannerView: View {
var body: some View {
GeometryReader { geo in
let w = geo.size.width
let h = geo.size.height
Image("animal_01")
.resizable()
.frame(width: w, height: h)
.aspectRatio(contentMode: .fit)
}
}
struct ImageScrollBannerView_Previews: PreviewProvider {
static var previews: some View {
ImageScrollBannerView()
.previewLayout(.fixed(width: 300, height: 300))
}
}
간단한 샘플. 프리뷰 코드에서 보듯이 300, 300 이 이 컴포넌트의 테스트 크기이다.
여기서 GeometryReader 를 통해 body 의 값을 가져오면 300, 300 의 값을 획득할 수 있다.
GeometryReader { geo in
let w = geo.size.width
let h = geo.size.height
// w = 300 획득.
// h = 300 획득.
}
이제 이 값을 기준으로 이미지를 그리면 딱맞게 떨어진다. 주의할것은 여기서의 GeometryReader 는 body 바로 아래에 있기 떄문에 상위뷰가 300, 300 으로 떨어진 것이다. 아래처럼 200, 200 의 뷰 안에 같은 코드를 넣으면...
HStack {
GeometryReader { geo in
let w = geo.size.width
let h = geo.size.height
Image("animal_01")
.resizable()
.frame(width: w, height: h)
.aspectRatio(contentMode: .fit)
}
}.frame(width: 200, height: 200)
HStack 의 크기인 200, 200 이 w, h 에 적용된다.
즉, 자신의 바로 상위뷰의 크기를 가져올 수 있다.