【问题标题】:LazyVStack scrolling stops animationsLazyVStack 滚动停止动画
【发布时间】:2021-01-17 17:52:29
【问题描述】:

此代码列出了 100 行带有刷新图标动画的行。当使用LazyVStack 而不是VStack 时,向下滚动到此列表的底部后,所有动画都会停止,包括在您向后滚动时位于列表顶部的动画。 VStack 没有此类问题。关于为什么会发生这种情况的任何想法以及是否有解决方法? 使用 Xcode 12.0.1、iOS 14、Swift 5

struct RefreshingList : View {
    @State var isAnimating = false

    var body: some View {
        ScrollView {
            LazyVStack { // <- change to VStack to have animations not stop
                ForEach(0..<100, id: \.self) { i in
                    HStack {
                        Text("\(i) -> ")
                        self.button()
                    }
                }
            }
        }
        .onAppear {
            self.isAnimating=true
        }
    }
    
    func button() -> some View {
        Button(action: {}, label: {
            Image(systemName: "arrow.2.circlepath")
                .rotationEffect(Angle(degrees: self.isAnimating ? 360.0 : 0.0))
                .animation(Animation.linear(duration: 2.0)
                            .repeatForever(autoreverses: false))
        })
    }
}

【问题讨论】:

    标签: swiftui vstack lazyvstack


    【解决方案1】:

    当观察到屏幕上的视图发生变化时,动画就会发生。在VStack 中,所有视图都是立即创建的,因此 SwiftUI 能够观察到所有视图的旋转值的变化。

    LazyVStack 的情况下,仅根据需要创建视图,因此当.onAppear 中的旋转值更改时,底部的视图不会出现在屏幕上。当它们确实出现在屏幕上时,它的值已经更改,因此不会发生动画。

    解决此问题的一种方法是让按钮拥有.isAnimating @State 变量。然后任何时候创建一个,它都会有动画。

    struct RefreshingList : View {
    
        var body: some View {
            ScrollView {
                LazyVStack {
                    ForEach(0..<100, id: \.self) { i in
                        HStack {
                            Text("\(i) -> ")
                            AnimatedButton()
                        }
                    }
                }
            }
        }
    }
    
    struct AnimatedButton: View {
        @State var isAnimating = false
        
        var body: some View {
            Button(action: {
                
            }, label: {
                Image(systemName: "arrow.2.circlepath")
                    .rotationEffect(Angle(degrees: self.isAnimating ? 360.0 : 0.0))
                    .animation(Animation.linear(duration: 2.0)
                                .repeatForever(autoreverses: false))
            })
            .onAppear {
                isAnimating = true
            }
        }
    }
    

    【讨论】:

      【解决方案2】:
      struct RefreshingListView: View {
          var body: some View {
              ScrollView {
                  LazyVStack {
                      ForEach(0..<100) {
                          LabelView(id: $0)
                              .id($0)
                      }
                  }
                  .animation(
                      Animation
                          .linear(
                              duration: 2)
                          .repeatForever(
                              autoreverses: false))
      
              }
          }
      }
      
      struct LabelView: View {
          @State var
              animate = false
          var id: Int
          var body: some View {
              Label(
                  title: {
                      Text("<- \(id)")
                  }, icon: {
                      Image(
                          systemName:
                              "arrow.2.circlepath")
                          .foregroundColor(.blue)
                          .padding(.horizontal)
                          .rotationEffect(
                              Angle(
                                  degrees:
                                      animate ?
                                      360 : 0))
                  }
              )
              .onAppear {
                  animate
                      .toggle()
              }
          }
      }
      

      【讨论】:

      • 这种方法有效,但现在有不同的副作用。当我向下滚动到底部时,动画继续正常。但是当我向上滚动到顶部时,动画会反向旋转(CCW 与 CW)。如果我再次向下滚动,动画将再次反转。动画不会停止,而是反向。
      猜你喜欢
      • 1970-01-01
      • 2011-09-16
      • 1970-01-01
      • 2015-01-15
      • 2016-03-27
      • 1970-01-01
      • 1970-01-01
      • 2015-12-26
      • 2018-07-31
      相关资源
      最近更新 更多