SwiftUI中ScrollViewReader滚动至Section Header带内边距的问题
解决SwiftUI中ScrollViewReader滚动Section Header被截断的问题
问题原因
你当前把id绑定在Section内部的Text组件上,而List的Section头部本身带有容器内边距,滚动时会将Text的顶部对齐到滚动视图顶端,导致Section Header的容器内边距部分被截断。另外如果日期包含时间组件,可能会出现scrollTo目标ID不匹配的情况。
修复方案
- 将ID绑定到Section本身:让ScrollViewReader直接定位整个Section,而非内部的Text,这样会自动包含Section头部的内边距,避免截断。
- 日期归一化:将日期统一转换为当天零点,避免因时间组件差异导致ID匹配失败。
修改后的完整代码
ScrollViewReader { proxy in List(selection: $selectedFlights) { ForEach(flightStore.flightsGroupedByDate.prefix(sectionsLoaded), id: \.date) { groupedFlights in // 把ID从header的Text移到Section上 Section(header: Text("\(groupedFlights.date.abbreviatedOmitted)") .foregroundStyle(Color.primary) .fontWeight(.heavy) ) { ForEach(groupedFlights.flights, id: \.id) { flight in ZStack { NavigationLink(value: flight) { EmptyView() }.opacity(0) FlightCell(flight: flight) .listRowInsets(EdgeInsets(top: 5, leading: 0, bottom: 5, trailing: 0)) .swipeActions(edge: .leading) { swipeActionsLeading(for: flight) } .swipeActions(edge: .trailing) { swipeActionsTrailing(for: flight) } } .tag(flight.id) } } // 使用当天零点作为ID,避免时间组件干扰 .id(Calendar.current.startOfDay(for: groupedFlights.date)) .onAppear { if groupedFlights == flightStore.flightsGroupedByDate[min(sectionsLoaded-1, flightStore.flightsGroupedByDate.count-1)] { loadMoreSections() print("loading more sections") } } } } .onChange(of: calendarVM.currentDate, perform: { newDate in withAnimation { // 滚动目标也使用当天零点的日期 proxy.scrollTo(Calendar.current.startOfDay(for: newDate), anchor: .top) } }) }
额外说明
- 如果你的页面包含导航栏,确保List正确适配安全区域,可以添加
.navigationBarTitleDisplayMode(.inline)或调整.safeAreaInset来避免头部被导航栏遮挡。 - 确认
flightStore.flightsGroupedByDate中的日期已经正确按天分组,避免同一日期出现多个Section导致滚动混乱。
内容的提问来源于stack exchange,提问作者Petr Smejkal
相关产品推荐
相关产品推荐

