I have a fairly simple view.
It’s a trip itinerary with two parts:
-
A horizontally scrolling list of dates at the top of the page.
-
A vertically scrolling list of days (each day contains many trip stops).
I’ve added logic for .scrollPosition() so that as the user scrolls the vertical list, the horizontal list can update which day the user is currently active on the page.
Similarly, when a user taps on a day in the horizontal list at the top of the page, I have it set up to automatically scroll down to that day in the vertical list.
Here is that code:
struct TripView: View {
@Environment(\.dismiss) private var dismiss
@Binding var trip: Trip
@State private var activeDate: String?
var body: some View {
VStack(spacing: 0) {
// HORIZONTAL DATE PICKER
ScrollViewReader { proxy in
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 16) {
ForEach(trip.days, id: \.id) { day in
Button(action: {
withAnimation(.spring(duration: 0.3)) {
activeDate = day.date
}
}, label: {
VStack(spacing: 2) {
Text(day.date.formatDate(fromFormat: "yyyy-MM-dd", toFormat: "d") ?? "")
.background(activeDate == day.date ? Color.blue : Color.clear)
}
})
.id(day.date)
}
}
}
.onChange(of: activeDate) { oldValue, newValue in
print("Active date changed to: \(newValue)")
if let newValue {
withAnimation {
proxy.scrollTo(newValue, anchor: .center)
}
}
}
}
// VERTICAL CONTENT LIST
ScrollView {
LazyVStack(spacing: 0) {
ForEach($trip.days) { $day in
TripDayView(
tripId: trip.id,
day: $day
)
.id(day.date)
}
}
.scrollTargetLayout()
}
.scrollPosition(id: $activeDate, anchor: .top)
}
}
}
The problem I’m facing is inside TripDayView below.
struct TripDayView: View {
@EnvironmentObject var tripManager: TripManager
let tripId: Int
@Binding var day: Day
@State private var showingActionSheet: Bool = false
var body: some View {
Section {
headerView
ListStopsView(tripId: tripId, stops: $day.stops)
}
}
var headerView: some View {
VStack(alignment: .leading, spacing: 0) {
HStack(spacing: 0) {
VStack(alignment: .leading, spacing: 0) {
Text(day.date.formatDate(fromFormat: "yyyy-MM-dd", toFormat: "EE, MMM d") ?? "")
}
Spacer()
Button(action: {
showingActionSheet = true
}, label: {
Image("Ellipsis Vertical")
})
.confirmationDialog("", isPresented: $showingActionSheet, titleVisibility: .hidden) {
Button("Option 1") {
//
}
Button("Option 2") {
//
}
Button("Option 3") {
//
}
}
}
}
}
}
When I tap on the Button (that sets showingActionSheet = true), the vertical list in TripView scrolls up when the confirmationDialog is shown.
What is causing this? How can I fix it?
It seems to be related to .scrollPosition() because when I comment out that line, it doesn’t scroll up when I tap the button. But I need to keep that functionality.