LazyVStack滚动停止动画

问题描述

代码列出了带有刷新图标动画的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))
        })
    }
}

解决方法

当观察到屏幕视图发生更改时,就会发生动画。在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
        }
    }
}
,
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()
        }
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...