SwiftUI列表快速滚动/拖拽报错及标题动画卡顿问题求助
SwiftUI列表滚动异常问题修复
问题现象
- 快速滚动列表或多次上下拖拽时,触发
Invalid sample AnimatablePair...错误,提示时间戳异常 - 顶部"Scroll Up or down"关联的标题字体动画卡顿、不流畅
问题根源
- 手势冲突:自定义
DragGesture通过simultaneousGesture绑定到List,与List原生滚动手势同时触发,导致动画系统接收到时序混乱的帧数据,抛出时间戳错误 - 状态频繁更新:
DragGesture.onChanged每帧都会触发,频繁更新isUp状态,导致动画被反复打断,出现卡顿
修复方案及代码
import SwiftUI struct ContentView: View { @State var items = listData @State var isUp: Bool = true @State var initialDragDirection: Bool? var body: some View { NavigationStack { List { ForEach(items) { item in Text(item.title) } } .padding(.vertical) // 替换simultaneousGesture为普通gesture,设置最小拖拽距离过滤无效操作 .gesture( DragGesture(minimumDistance: 5) .onChanged { value in // 用拖拽偏移量判断方向,比实时位置更准确 let currentDirection = value.translation.y < 0 // 仅在拖拽方向明确且持续时更新状态,避免频繁切换 if initialDragDirection == nil { initialDragDirection = currentDirection } else if initialDragDirection == currentDirection { isUp = currentDirection } } .onEnded { _ in initialDragDirection = nil } ) .listStyle(.plain) .toolbarBackground(.hidden, for: .navigationBar) .toolbar { ToolbarItem(placement: .principal) { Text("Scroll \(isUp ? "up" : "down")") } } .safeAreaInset(edge: .top, content: { VStack { Text("John") .font(isUp ? .title : .largeTitle) .animation(.easeIn(duration: 0.2), value: isUp) Text("Test") .font(isUp ? .title : .largeTitle) .animation(.easeIn(duration: 0.2), value: isUp) } }) } } } #Preview { ContentView() } struct ContentItem: Identifiable { var id: UUID = UUID() var title: String } var listItems = Array(repeating: "Hello", count: 100) var listData = listItems.map { ContentItem(title: $0) }
修复说明
- 移除
simultaneousGesture避免与List原生滚动手势冲突,设置minimumDistance: 5过滤微小滑动,减少无效状态更新 - 使用
translation.y判断拖拽方向(偏移量<0为向上滑),比实时location.y更稳定,不受屏幕位置影响 - 新增
initialDragDirection变量,确保只有当拖拽方向明确且持续时才更新isUp,避免快速滚动时的方向频繁切换 - 将动画直接绑定到
font属性上,而非容器视图,让动画系统更高效处理属性变化,提升流畅度
内容的提问来源于stack exchange,提问作者NNikN
相关产品推荐
相关产品推荐

