I have an array of years and a selected year. What I want is whenever my View loads, it should move automatically to the selected year.
Here is my code:
struct Testing: View {
let years = ["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025", "2026"]
@State var selectedYear = "2023"
@Namespace private var animation
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
ForEach(years.indices, id: \.self) { index in
Button {
withAnimation(.linear(duration: 0.5)) {
selectedYear = years[index]
}
} label: {
VStack {
Text("\(years[index])")
.foregroundColor(.white)
.fontWeight(.semibold)
.padding(.horizontal, 15)
if selectedYear == years[index] {
Capsule()
.fill(.white)
.frame(height: 5)
.padding(.horizontal, -5)
}
}
}
}
}.padding().background {
Rectangle()
.fill(Color.purple)
}
}
}
}
This is returning
Whenever the View loads it should show the selectedYear in the middle. How can I achieve this?
You can use ScrollViewReader
container view which gives a mechanism to read a scroll view's content offset and scroll to a particular piece of material therein with scrollTo
method.
Here is the Updated code:
struct Testing: View {
let years = ["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025", "2026"]
@State var selectedYear = "2023"
@Namespace private var animation
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
ScrollViewReader { scrollView in // --> Here
HStack(spacing: 20) {
ForEach(years.indices, id: \.self) { index in
Button {
withAnimation(.linear(duration: 0.5)) {
selectedYear = years[index]
}
} label: {
VStack {
Text("\(years[index])")
.foregroundColor(.white)
.fontWeight(.semibold)
.padding(.horizontal, 15)
if selectedYear == years[index] {
Capsule()
.fill(.white)
.frame(height: 5)
.padding(.horizontal, -5)
}
}
.id(years[index]) // ---> Here
}
}
}
.padding().background {
Rectangle()
.fill(Color.purple)
}
.onAppear {
scrollView.scrollTo(selectedYear, anchor: .center) // ---> Here
}
}
}
}
}