Skip to content

Instantly share code, notes, and snippets.

@Joony
Created November 11, 2022 12:31
Show Gist options
  • Save Joony/8aecad991fc947d2788669aca9e42737 to your computer and use it in GitHub Desktop.
Save Joony/8aecad991fc947d2788669aca9e42737 to your computer and use it in GitHub Desktop.
SwiftUI - Have a child view report its size to a parent.
import SwiftUI
struct ViewSize: ViewModifier {
struct ViewSizePreferenceKey: PreferenceKey {
typealias Value = CGSize
static var defaultValue: Value = .zero
static func reduce(value _: inout Value, nextValue: () -> Value) {
_ = nextValue()
}
}
func body(content: Content) -> some View {
content
.background(
GeometryReader { proxy in
Color.clear
.preference(key: ViewSizePreferenceKey.self, value: proxy.size)
}
)
}
}
extension View {
func viewSize(size: @escaping (CGSize) -> ()) -> some View {
modifier(ViewSize())
.onPreferenceChange(ViewSize.ViewSizePreferenceKey.self) { preferences in
size(preferences)
}
}
}
struct ViewSize_Previews: PreviewProvider {
struct ViewSizePreviewView: View {
@State private var size: CGSize = .zero
@State private var width: CGFloat = 100
@State private var height: CGFloat = 100
var body: some View {
VStack {
Spacer()
Text("width: \(size.width), height: \(size.height)")
.frame(width: width, height: height)
.background(Color.red.opacity(0.3))
.viewSize { size in
self.size = size
}
Spacer()
Slider(value: $width, in: 100...300) {
EmptyView()
}
.padding(.horizontal)
Slider(value: $height, in: 100...300) {
EmptyView()
}
.padding(.horizontal)
}
}
}
static var previews: some View {
ViewSizePreviewView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment