Skip to content

Instantly share code, notes, and snippets.

@agelessman
Created July 13, 2020 11:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agelessman/15ca41fdd8a4d7edb5ba9d48962124f3 to your computer and use it in GitHub Desktop.
Save agelessman/15ca41fdd8a4d7edb5ba9d48962124f3 to your computer and use it in GitHub Desktop.
//
// ContentView.swift
// AnchorPreferencesDemo
//
// Created by MC on 2020/7/13.
//
import SwiftUI
struct ContentView: View {
var body: some View {
Example1()
}
}
struct Example1: View {
@State private var titles = ["推荐", "要闻", "视频", "抗疫", "北京",
"新时代", "娱乐", "体育", "军事", "NBA",
"科技", "财经", "时尚"]
@State private var selectedIndex: Int = 0
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 0) {
ForEach(0..<titles.count) { index in
SegementItem(title: titles[index],
index: index,
selectedIndex: selectedIndex)
.onTapGesture {
withAnimation {
self.selectedIndex = index
}
}
}
}
}
.backgroundPreferenceValue(MySegementPreferenceKey.self) { preferences in
GeometryReader { proxy in
self.createBottomLine(proxy, preferences: preferences)
}
}
}
struct SegementItem: View {
let title: String
let index: Int
let selectedIndex: Int
var body: some View {
Text(title)
.scaleEffect(index == self.selectedIndex ? 1.5 : 1.0)
.font(.title)
.foregroundColor(index == self.selectedIndex ? .primary : .secondary)
.padding(.all, /*@START_MENU_TOKEN@*/10/*@END_MENU_TOKEN@*/)
.anchorPreference(key: MySegementPreferenceKey.self, value: .bounds, transform: {
[MySegementPreferenceData(viewIdx: index, bounds: $0)]
})
.transformAnchorPreference(key: MySegementPreferenceKey.self, value: .topLeading, transform: { (value: inout [MySegementPreferenceData], anchor: Anchor<CGPoint>) in
value[0].topLeading = anchor
})
}
}
func createBottomLine(_ proxy: GeometryProxy, preferences: [MySegementPreferenceData]) -> some View {
let p = preferences.first(where: { $0.viewIdx == self.selectedIndex })
let bounds = proxy[p!.bounds]
return RoundedRectangle(cornerRadius: 2.5)
.foregroundColor(.green)
.frame(width: bounds.width, height: 5)
.offset(x: bounds.minX, y: bounds.height - 5)
// .animation(.easeInOut)
}
}
struct MySegementPreferenceData {
let viewIdx: Int
let bounds: Anchor<CGRect>
var topLeading: Anchor<CGPoint>? = nil
}
struct MySegementPreferenceKey: PreferenceKey {
typealias Value = [MySegementPreferenceData]
static var defaultValue: Value = []
static func reduce(value: inout [MySegementPreferenceData], nextValue: () -> [MySegementPreferenceData]) {
value.append(contentsOf: nextValue())
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment