【问题标题】:Horizontal ScrollView bounces vertically in SwiftUI on change水平 ScrollView 在 SwiftUI 中在更改时垂直反弹
【发布时间】: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)
              }
            }
         }
    }
}
}

【问题讨论】:

    标签: ios swift animation swiftui scrollview


    【解决方案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

      【讨论】:

        猜你喜欢
        • 2020-09-23
        • 2019-11-29
        • 2011-11-08
        • 2021-08-02
        • 2018-10-02
        • 2015-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多