繁体   English   中英

水平滚动视图在 SwiftUI 中在更改时垂直反弹

[英]Horizontal ScrollView bounces vertically in SwiftUI on change

我在 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)
              }
            }
         }
    }
}
}

问题是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 padding 从HStack删除垂直填充,然后将.vertical padding 添加到每个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)
    }
}
前 后

proxy.scrollTo(index, anchor: ...)使用.bottom而不是.center


如果我们设置 .top 或 .center 锚点,则在proxy.scrollTo动画期间垂直内容偏移会发生变化。 它看起来像一些苹果虫。 为了避免这种情况,我们应该对齐这样的锚点,这会在滚动期间导致零偏移。

对于水平 ScrollView 我们应该改变:

  • .trailing -> .bottomTrailing
  • .center -> .bottom
  • .lead -> .bottomLeading

对于垂直:

  • .top -> .topTrailing
  • .center -> .trailing
  • .bottom -> .bottomTrailing

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM