SwiftUI GeometryReader 教學
在 SwiftUI 中,View 通常會自動適應內容大小。但有時候,我們需要知道父容器的具體尺寸,或是某個 View 在螢幕上的座標位置,這時候就需要 GeometryReader。
獲取尺寸 (Size)
GeometryReader 是一個特殊的 View,它會回傳一個 GeometryProxy 物件,透過這個物件我們可以讀取剩餘空間的大小。
GeometryReader 會盡可能佔滿所有可用空間,這點跟大多數 View 只佔用最小空間的行為不同。請小心使用,以免意外撐大佈局。
GeometryReader { geometry in
VStack {
Text("寬度: \(geometry.size.width)")
Text("高度: \(geometry.size.height)")
Rectangle()
.fill(.blue)
.frame(width: geometry.size.width / 2) // 使用一半的寬度
}
}
.frame(height: 200) // 強制指定 GeometryReader 的高度
獲取座標 (Frame & Coordinates)
除了尺寸,GeometryProxy 也可以告訴我們 View 在不同座標系中的位置。
.local: 相對於 GeometryReader 本身的座標 (通常原點 (0,0) 在左上角)。.global: 相對於整個螢幕 (Window) 的座標。
這在製作複雜的滾動特效(例如 Parallax 視差效果)時非常有用。
簡單的視差滾動範例
ScrollView {
VStack {
ForEach(0..<10) { _ in
GeometryReader { geo in
Image("nature")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: geo.size.width, height: 200)
// 根據 Y 軸位置製造視差位移
.offset(y: -geo.frame(in: .global).minY / 5)
}
.frame(height: 200)
.clipped()
}
}
}
何時該使用?
雖然 GeometryReader 很強大,但它是比較重的操作。在絕大多數的版面佈局需求中(例如兩欄均分),應該優先使用 HStack + Spacer 或是 .frame(maxWidth: .infinity) 來達成,只有在真的需要精確數值計算時才使用 GeometryReader。