You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI ScrollPosition滚动可变高度元素不可靠的解决方案咨询

SwiftUI ScrollPosition 程序化滚动失效的解决方案求助

我的项目完全基于SwiftUI,主视图的ScrollView中包含大量高度各不相同的元素。尝试用SwiftUI的ScrollPosition实现程序化滚动到指定元素时,多数情况有效但偶尔失效,已排除自身代码存在Bug的可能。

问题演示:
Animation showing the bug

完整复现代码:

import SwiftUI

struct ContentView: View {
    @State private var position = ScrollPosition(idType: Int.self)
    @State private var requestedPosition: String = ""
    private let heights: [Double] = (0..<10_000).map { _ in Double.random(in: 150...300) }
    
    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(0..<10_000) { i in
                    Text(String(i))
                        .frame(height: heights[i])
                        .frame(maxWidth: .infinity)
                        .background(i % 2 == 0 ? Color.blue : Color.red)
                        .id(i)
                }
            }.scrollTargetLayout(isEnabled: false)
        }
        .scrollPosition($position, anchor: .top)
        .overlay(alignment: .bottom) {
            HStack {
                Text("At: \(position.viewID(type: Int.self) ?? -1)")
                Spacer()
                TextField("Go to", text: $requestedPosition).frame(width: 100)
                Button("Go") {
                    position.scrollTo(id: Int(requestedPosition), anchor: .top)
                }
            }
            .padding()
            .background(Color.white)
        }
    }
}

操作步骤

  • 在文本框中输入数字(如8674),点击"Go"跳转
  • 再输入其他数字(如401、5678等)重复操作

问题表现

  • 有时最终显示的视图不正确,目标ID与当前可见ID的差距越大,出现问题的概率越高
  • 更严重的是:读取position变量时,返回的是目标ID,但实际并未滚动到对应位置!这导致无法通过程序判断问题何时发生,也就无法通过延迟重试等方式补救。比如演示中尝试滚动到305,最终停在302,但position仍显示305,且305完全不在屏幕内。

问题成因推测

SwiftUI无法提前知晓每个元素的准确高度,它会计算目标元素的预估y坐标进行滚动,但偶尔会放弃精确计算,滚动到近似位置。

求助问题

如何最优地解决该问题?我知道可以用UICollectionView,但希望避免引入UIKit组件;也曾尝试多次延迟滚动,虽有改善但无法彻底解决。有没有开发者找到可行的workaround?

内容的提问来源于stack exchange,提问作者InsightClip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 14:53:10