The Dimensions view takes any combination of views and shows the width & height of all the views combined using PreferenceKeys.
As seen in Example 1: When constructing all the views inside Dimensions, it will work and show the sizes.
While in Examples 2 & 3: If the views are constructed outside of Dimensions, it will not work.
QUESTION: How would it work when the views are constructed outside? Thanks.
Running on Xcode Version 12.5.1 (12E507) target iOS 14.5
The code:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
// Example 1
Dimensions {
HStack {
Text("Hello, world!")
.padding()
// HelloWorldVariable // <===== THIS WILL BREAK IT
// HelloWorldView() // <===== THIS WILL BREAK IT
}
}.background(Color.blue)
// Example 2
Dimensions {
HStack {
HelloWorldVariable // <===== THIS DOES NOT WORK in the HStack
}
}.background(Color.green)
// Example 3
Dimensions {
HStack {
HelloWorldView() // <===== THIS DOES NOT WORK in the HStack
}
}.background(Color.yellow)
}
}
private var HelloWorldVariable: some View {
Text("Hello, world!")
.padding()
}
}
// MARK:- HelloWorldView
struct HelloWorldView: View {
var body: some View {
Text("Hello, world!")
.padding()
}
}
// MARK:- Dimensions
struct Dimensions<Content: View>: View {
private var content: () -> Content
@State private var contentSize: CGSize = .zero
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
var body: some View {
VStack {
content()
.background(ObserveViewDimensions())
VStack {
Text("contentWidth \(contentSize.width)")
Text("contentHeight \(contentSize.height)")
}
}
.onPreferenceChange(DimensionsKey.self, perform: { value in
self.contentSize = value
})
}
}
// MARK:- ObserveViewDimensions
struct ObserveViewDimensions: View {
var body: some View {
GeometryReader { geometry in
Color.clear.preference(key: DimensionsKey.self, value: geometry.size)
}
}
}
// MARK:- DimensionsKey
struct DimensionsKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
typealias Value = CGSize
}
// MARK:- Preview
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}