LazyVStack 滚动停止动画 [英] LazyVStack scrolling stops animations

查看:36
本文介绍了LazyVStack 滚动停止动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This code lists 100 rows with refresh icon animations. When using a LazyVStack instead of a VStack, after scrolling down to the bottom of this list all the animations stop, including those at the top of the list once you scroll back. No such issues with a VStack. Any ideas as to why this is happening and is there a workaround? Using 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))
        })
    }
}

推荐答案

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

Animation happens when a change to a view on screen is observed. In the VStack all of the views are created immediately so SwiftUI is able to observe the change in rotation value for all views.

LazyVStack 的情况下,视图只在需要时创建,所以当 .onAppear 中的旋转值改变时,底部的视图不会出现在屏幕上.当它们确实出现在屏幕上时,它具有已更改的值,因此不会发生动画.

In the LazyVStack case, the views are only created as needed, so the bottom ones aren't on screen when the rotation value changes in .onAppear. When they do appear on screen, it is with the already changed value, so no animation happens.

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

One way to fix this is to let the buttons own the .isAnimating @State variable. Then anytime one is created, it will be animating.

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
        }
    }
}

这篇关于LazyVStack 滚动停止动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆