GeometryReaderでは親のViewのサイズを取得することができます。
ですが、子のViewのサイズは取得することができないので、ChildGeometryReaderというものを作っていきたいと思います。
実装
struct ChildGeometryReader<Content: View>: View {
@Binding var size: CGSize
let content: () -> Content
var body: some View {
ZStack {
content()
.background(
GeometryReader { proxy in
Color.clear
.preference(key: SizePreferenceKey.self, value: proxy.size)
}
)
}
.onPreferenceChange(SizePreferenceKey.self) { preferences in
self.size = preferences
}
}
}
struct SizePreferenceKey: PreferenceKey {
typealias Value = CGSize
static var defaultValue: Value = .zero
static func reduce(value _: inout Value, nextValue: () -> Value) {
_ = nextValue()
}
}
PreferenceKeyを用いて子から親のViewにSizeを通知しています。
onPreferenceChangesでSizeの変更を受け取っていて、そのクロージャ内でBindingの値を書き換えることで実現しています。
使用方法
struct HogeView: View {
@State var size: CGSize = .zer
var body: some View {
ChildGeometryReader(size: $size) {
FugaView()
}
}
}
このようにして子のViewのSizeを取得することができました!
参考