/*
* Required:
* - 🌀CGRect + .frame
* - 🌀GeometryProxy + 🅿️ Rectangular
*/
import SwiftUI
import PlaygroundSupport
// ⭐️ custom preference key
struct SizePreferenceKey: PreferenceKey {
// default value
static let defaultValue: CGSize? = nil
// combine values from different child views
static func reduce(value: inout CGSize?, nextValue: () -> CGSize?) {
value = value ?? nextValue() // nil or first non-nil value
}
}
// 🌅 CircleText
struct CircleText: View {
// ⭐️ Text's favorite size (a square)
@State private var size: CGSize?
// local variables
let text : String // text of Text
var color: Color = .pink // bg color of Text
// view body
var body: some View {
Text(text)
.padding()
// ⭐️ 1. set optional frame (🌀CGRect + .frame)
.frame(size)
// ⭐️ 2. set bg color
.background(GeometryReader { geo in // ⭐️ 3. read Text's size
self.color
// ⭐️ 4. set preference:
// tell parent view its favorite size (a square)
// - 🌀GeometryProxy + 🅿️ Rectangular
.preference(key: SizePreferenceKey.self, value: geo.boundingSquare.size)
})
.clipShape(Circle())
// ⭐️ 5. parent view update itself in response to the preference change
.onPreferenceChange(SizePreferenceKey.self) { self.size = $0 }
}
}
// live view
struct ContentView: View {
var body: some View {
HStack {
Group {
// 🌅 CircleText
CircleText(text: "Hello, World")
CircleText(text: "Hello", color: .blue)
}// Group
.border(Color.black)
}// HStack (container)
.padding()
.background(Color.gray)
.shadow(radius: 8).shadow(radius: 8)
}
}
PlaygroundPage.current.setLiveView(ContentView())