使用scrollPosition(id:anchor:)锚定中心时选中项错误求助
SwiftUI横向滚动视图正确获取居中项的技巧
你遇到的问题核心在于scrollPosition(id:anchor:)的锚点计算是基于滚动视图的可滚动内容区域,直接给ScrollView添加contentMargins会让容器边距干扰锚点判定逻辑,导致选中项和视觉中心不匹配。
以下是修复后的实现方案:
修复步骤与代码示例
- 将
contentMargins移至LazyHStack内部,确保滚动内容范围包含边距,让锚点计算基于正确的内容区域。 - 添加
scrollTargetBehavior(.viewAligned),确保滚动停止时视图严格对齐到目标位置,避免半选中情况。
struct ScrollPositionSample: View { let words = "Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod".components(separatedBy: " ") @State private var selection: String? = "Lorem" var body: some View { VStack { if let selection { Text("Selected: \(selection)") .font(.title3) } ScrollView(.horizontal) { LazyHStack { ForEach(words, id: \.self) { word in Text(word) .font(.title2) .padding() .background(.teal, in: RoundedRectangle(cornerRadius: 5.0)) } } // 将边距移到内容内部,让滚动区域包含这些边距 .contentMargins(.leading, 100) .contentMargins(.trailing, 40) .scrollTargetLayout() .frame(maxHeight: 125) } .scrollPosition(id: $selection, anchor: .center) // 添加视图对齐的滚动目标行为 .scrollTargetBehavior(.viewAligned) .overlay { Color.red.frame(width: 2) } } } }
额外优化建议
如果滚动项宽度差异较大,可以通过两种方式进一步确保居中准确性:
- 给每个项设置固定宽度:
Text(word) .font(.title2) .frame(width: 150) // 统一固定宽度 .padding() .background(.teal, in: RoundedRectangle(cornerRadius: 5.0))
- 启用分页模式滚动:
// 替换视图对齐为分页模式 .scrollTargetBehavior(.paging)
内容的提问来源于stack exchange,提问作者RL2000
相关产品推荐
相关产品推荐

