Skip to content

Instantly share code, notes, and snippets.

@ashleymills
Created February 24, 2020 12:27
Show Gist options
  • Save ashleymills/d75bd7fd84342a7ca74ce57ce7ca2bbd to your computer and use it in GitHub Desktop.
Save ashleymills/d75bd7fd84342a7ca74ce57ce7ca2bbd to your computer and use it in GitHub Desktop.
A solution to SwiftUI Challenge #3: Tab Selection (https://twitter.com/objcio/status/1230145263202758658)
struct TabRectsKey: PreferenceKey {
static var defaultValue: [Int: CGRect] = [:]
static func reduce(value: inout [Int : CGRect], nextValue: () -> [Int : CGRect]) {
value.merge(nextValue(), uniquingKeysWith: { r1, r2 in r1 })
}
}
struct TabBar: View {
var items: [(Image, Text)]
@State var selectedIndex: Int = 0
@State var rects: [Int: CGRect] = [:]
var body: some View {
VStack(alignment: .leading, spacing: 0) {
HStack {
ForEach(0..<items.count, id: \.self) { index in
VStack {
self.items[index].0
self.items[index].1
}
.background(
GeometryReader { proxy in
Rectangle().hidden()
.preference(key: TabRectsKey.self, value: [index: proxy.frame(in: .named("TabContainer"))])
}
)
.foregroundColor(self.selectedIndex == index ? .blue : .black)
.onTapGesture {
self.selectedIndex = index
}
}
}
.coordinateSpace(name: "TabContainer")
Rectangle()
.frame(width: rects[selectedIndex]?.width, height: 2)
.foregroundColor(.blue)
.offset(x: rects[selectedIndex]?.minX ?? 0, y: 0)
.animation(.default)
}
.onPreferenceChange(TabRectsKey.self) { value in
self.rects = value
}
}
}
struct ContentView: View {
var body: some View {
return TabBar(items: [
(Image(systemName: "tray"), Text("Inbox")),
(Image(systemName: "archivebox"), Text("Archive")),
(Image(systemName: "doc.text"), Text("Drafts"))
])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment