水平 ScrollView 在 SwiftUI 中在更改时垂直反弹
Posted
技术标签:
【中文标题】水平 ScrollView 在 SwiftUI 中在更改时垂直反弹【英文标题】:Horizontal ScrollView bounces vertically in SwiftUI on change 【发布时间】:2021-09-23 11:59:10 【问题描述】:我在 ios 15 中遇到了ScrollView
的问题。
使用scrollTo
时,项目垂直弹跳。
我在 iOS 14 中没有这个问题。弹跳是非常随机的,根本没有逻辑来试图了解它何时会跳动。
如果我从滚动视图中删除填充,它是固定的,但我需要 UI 设计师要求的额外空间。
另外,尝试使用.frame
而不是.padding
并且结果相同。
有谁知道如何解决这个问题,或者为什么它只发生在 iOS 15 中?
代码:
ScrollView(.horizontal, showsIndicators: false)
ScrollViewReader proxy in
HStack(spacing: 32)
ForEach(...) index in
QuestionCell(...)
.scaleEffect(selectedIndex == index ? 1.175 : 1.0)
.onTapGesture
withAnimation(.spring())
selectedIndex = index
.padding(.leading)
.padding() // Removing this fixes the bounce bug.
.onChange(of: selectedIndex) value in
withAnimation(.spring())
let paramsCount = <SOME MODEL>.count
if value < paramsCount
proxy.scrollTo(value, anchor: .center)
else
proxy.scrollTo(paramsCount - 1, anchor: .center)
【问题讨论】:
【参考方案1】:问题是HStack
上的垂直填充。
问题的最小可重现示例
这是任何人都可以运行的最少代码的问题。使用此代码作为参考,看看有什么变化:
struct ContentView: View
@State private var selectedIndex = 0
var body: some View
ScrollView(.horizontal, showsIndicators: false)
ScrollViewReader proxy in
HStack(spacing: 32)
ForEach(0 ..< 10, id: \.self) index in
Text("Question cell at index: \(index)")
.background(Color(UIColor.systemBackground))
.scaleEffect(selectedIndex == index ? 1.175 : 1.0)
.onTapGesture
withAnimation(.spring())
selectedIndex = index
proxy.scrollTo(index, anchor: .center)
.padding(.leading)
.padding() // Removing this fixes the bounce bug
.background(Color.red)
解决方案
您可以通过执行.horizontal
填充来从HStack
中删除垂直填充,然后将.vertical
填充添加到每个Text
视图中。
代码:
struct ContentView: View
@State private var selectedIndex = 0
var body: some View
ScrollView(.horizontal, showsIndicators: false)
ScrollViewReader proxy in
HStack(spacing: 32)
ForEach(0 ..< 10, id: \.self) index in
Text("Question cell at index: \(index)")
.background(Color(UIColor.systemBackground))
.scaleEffect(selectedIndex == index ? 1.175 : 1.0)
.onTapGesture
withAnimation(.spring())
selectedIndex = index
proxy.scrollTo(index, anchor: .center)
.padding(.vertical) // <- HERE
.padding(.leading)
.padding(.horizontal) // <- HERE
.background(Color.red)
Before | After |
---|---|
【讨论】:
【参考方案2】:在proxy.scrollTo(index, anchor: ...)
中使用.bottom
而不是.center
。
如果我们设置 .top 或 .center 锚点,则在 proxy.scrollTo
动画期间垂直内容偏移会发生变化。它看起来像一些苹果虫。
为了避免这种情况,我们应该对齐这样的锚点,在滚动期间导致零偏移。
对于水平滚动视图,我们应该改变:
.trailing -> .bottomTrailing .center -> .bottom .leading -> .bottomLeading对于垂直:
.top -> .topTrailing .center -> .trailing .bottom -> .bottomTrailing【讨论】:
以上是关于水平 ScrollView 在 SwiftUI 中在更改时垂直反弹的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:NavigationLink 内的水平 ScrollView 会中断导航