Skip to content

Instantly share code, notes, and snippets.

@prafullakumar
Created February 7, 2021 07:48
Show Gist options
  • Save prafullakumar/fbeb8312824b6ce3d3037d869d7b3b51 to your computer and use it in GitHub Desktop.
Save prafullakumar/fbeb8312824b6ce3d3037d869d7b3b51 to your computer and use it in GitHub Desktop.
extension HorizontalAlignment {
private enum UnderlineLeading: AlignmentID {
static func defaultValue(in d: ViewDimensions) -> CGFloat {
return d[.leading]
}
}
static let underlineLeading = HorizontalAlignment(UnderlineLeading.self)
}
struct WidthPreferenceKey: PreferenceKey {
static var defaultValue = CGFloat(0)
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
typealias Value = CGFloat
}
struct ScrollableTabView : View {
@Binding var activeIdx: Int
@State private var w: [CGFloat]
private let dataSet: [String]
init(activeIdx: Binding<Int>, dataSet: [String]) {
self._activeIdx = activeIdx
self.dataSet = dataSet
_w = State.init(initialValue: [CGFloat](repeating: 0, count: dataSet.count))
}
var body: some View {
VStack(alignment: .underlineLeading) {
HStack {
ForEach(0..<dataSet.count) { i in
Text(dataSet[i])
.font(Font.title2.bold())
.modifier(ScrollableTabViewModifier(activeIdx: $activeIdx, idx: i))
.background(TextGeometry())
.onPreferenceChange(WidthPreferenceKey.self, perform: { self.w[i] = $0 })
.id(i)
Spacer().frame(width: 20)
}
}
.padding(.horizontal, 5)
Rectangle()
.alignmentGuide(.underlineLeading) { d in d[.leading] }
.frame(width: w[activeIdx], height: 4)
.animation(.linear)
}
}
}
struct TextGeometry: View {
var body: some View {
GeometryReader { geometry in
return Rectangle().fill(Color.clear).preference(key: WidthPreferenceKey.self, value: geometry.size.width)
}
}
}
struct ScrollableTabViewModifier: ViewModifier {
@Binding var activeIdx: Int
let idx: Int
func body(content: Content) -> some View {
Group {
if activeIdx == idx {
content.alignmentGuide(.underlineLeading) { d in
return d[.leading]
}.onTapGesture {
withAnimation{
self.activeIdx = self.idx
}
}
} else {
content.onTapGesture {
withAnimation{
self.activeIdx = self.idx
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment