ScrollView 中的初始 SwiftUI 动画

Initial SwiftUI Animation inside ScrollView

在我的应用程序中,我有一个 ScrollView,其中包含一个 VStackVStack 有一个 animation 修饰符。它还有一个带有 transition 修饰符的条件视图。过渡有效。但是,当视图首次出现时,内容会以起始宽度 0 放大。您可以在下面视频的绿色边框上看到这一点。仅当 VStackScrollView 内或 VStack 具有 animation 修饰符时才会发生这种情况。

我尝试了其他不同的设置,例如设置 fixedSize 或设置 animation(nil),但我无法让它工作。

我不在乎开头是否有动画或视图是否过渡到屏幕上。但我绝对不想要一开始的糟糕动画。当我点击按钮时,TextButton 都应该有动画效果。

我还使用以下简化代码测试了此行为。

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()

    var body: some View {
        ScrollView {
            VStack(spacing: 32) {
                if self.viewModel.shouldShowText {
                    Text("Hello, World! This is a some text.")
                        .transition(
                            AnyTransition
                                .move(edge: .top)
                                .combined(
                                    with:
                                        .offset(
                                            .init(width: 0, height: -100)
                                        )
                                )
                        )
                }

                Button(
                    action: {
                        self.viewModel.didSelectButton()
                    },
                    label: {
                        Text("Button")
                            .font(.largeTitle)
                    }
                )
            }
            .border(Color.green)
            .animation(.easeInOut(duration: 5))
            .border(Color.red)

            HStack { Spacer() }
        }
        .border(Color.blue)
    }
}

class ViewModel: ObservableObject {
    @Published private var number: Int = 0

    var shouldShowText: Bool {
        return self.number % 2 == 0
    }

    func didSelectButton() {
        self.number += 1
    }
}

它与 Xcode 12 / iOS 14(以及独立的和 NavigationView 一起工作正常),所以我认为它是以前版本中的 SwiftUI 错误。

无论如何,尝试使动画按如下所示的值激活(已测试并有效)

  // ... other code
}
.border(Color.green)
.animation(.easeInOut(duration: 5), value: viewModel.number)   // << here !!
.border(Color.red)

对于这项工作,它需要提供已发布的 属性 供观察

class BlockViewModel: ObservableObject {
    @Published var number: Int = 0             // << here !!
 
    // ... other code