Skip to content

Instantly share code, notes, and snippets.

@swiftui-lab
Last active March 16, 2022 09:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save swiftui-lab/abdd9a30e5a6e0830c8dffb142ae7794 to your computer and use it in GitHub Desktop.
Save swiftui-lab/abdd9a30e5a6e0830c8dffb142ae7794 to your computer and use it in GitHub Desktop.
// The SwiftUI Lab: https://swiftui-lab.com
// Article: Inspecting the View Tree – Part 2
// https://swiftui-lab.com/communicating-with-the-view-tree-part-2/
import SwiftUI
struct MyTextPreferenceData {
let viewIdx: Int
let bounds: Anchor<CGRect>
}
struct MyTextPreferenceKey: PreferenceKey {
typealias Value = [MyTextPreferenceData]
static var defaultValue: [MyTextPreferenceData] = []
static func reduce(value: inout [MyTextPreferenceData], nextValue: () -> [MyTextPreferenceData]) {
value.append(contentsOf: nextValue())
}
}
struct MonthView: View {
@Binding var activeMonth: Int
let label: String
let idx: Int
var body: some View {
Text(label)
.padding(10)
.anchorPreference(key: MyTextPreferenceKey.self, value: .bounds, transform: { [MyTextPreferenceData(viewIdx: self.idx, bounds: $0)] })
.onTapGesture { self.activeMonth = self.idx }
}
}
struct ContentView : View {
@State private var activeIdx: Int = 0
var body: some View {
VStack {
Spacer()
HStack {
MonthView(activeMonth: $activeIdx, label: "January", idx: 0)
MonthView(activeMonth: $activeIdx, label: "February", idx: 1)
MonthView(activeMonth: $activeIdx, label: "March", idx: 2)
MonthView(activeMonth: $activeIdx, label: "April", idx: 3)
}
Spacer()
HStack {
MonthView(activeMonth: $activeIdx, label: "May", idx: 4)
MonthView(activeMonth: $activeIdx, label: "June", idx: 5)
MonthView(activeMonth: $activeIdx, label: "July", idx: 6)
MonthView(activeMonth: $activeIdx, label: "August", idx: 7)
}
Spacer()
HStack {
MonthView(activeMonth: $activeIdx, label: "September", idx: 8)
MonthView(activeMonth: $activeIdx, label: "October", idx: 9)
MonthView(activeMonth: $activeIdx, label: "November", idx: 10)
MonthView(activeMonth: $activeIdx, label: "December", idx: 11)
}
Spacer()
}.backgroundPreferenceValue(MyTextPreferenceKey.self) { preferences in
return GeometryReader { geometry in
ZStack {
self.createBorder(geometry, preferences)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
}
}
}
func createBorder(_ geometry: GeometryProxy, _ preferences: [MyTextPreferenceData]) -> some View {
let p = preferences.first(where: { $0.viewIdx == self.activeIdx })
let bounds = p != nil ? geometry[p!.bounds] : .zero
return RoundedRectangle(cornerRadius: 15)
.stroke(lineWidth: 3.0)
.foregroundColor(Color.red)
.frame(width: bounds.size.width, height: bounds.size.height)
.fixedSize()
.offset(x: bounds.minX, y: bounds.minY)
.animation(.easeInOut(duration: 1.0))
}
}
@VonZen
Copy link

VonZen commented Oct 15, 2019

the offset is not right in iOS 13 released version.

@swiftui-lab
Copy link
Author

swiftui-lab commented Oct 15, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment