如何在使用 SwiftUI .move 过渡/动画时剪辑视图

LLo*_*ann 5 ios swift swiftui swiftui-animation

我正在尝试在视图中制作动画,并使其看起来像是从另一个视图打开的抽屉。这一切都很好,除非第一个视图不是不透明的。看来您可以在动画视图开始动画时看到它。有没有办法对其进行剪辑,以便视图看起来是从底部视图的顶部增长的?

即使没有不透明度,如果您的动画来源没有被覆盖,这也是一个问题(在第二个 gif 中演示)

动画示例 其他动画示例

示例代码:

struct ContentView: View {
    @State private var showingSecondView: Bool = false
    

    var body: some View {
        VStack(spacing: 0) {
            Spacer()
            if showingSecondView {
                ZStack {
                    Color.green.opacity(0.25)
                    Text("Second View")
                }
                .frame(width: 300, height: 300)
                .transition(.move(edge: .bottom))
            }
            ZStack {
                Color.black.opacity(1)
                Text("First View")
            }
            .frame(width: 300, height: 300)
            Button("Animate In / Out") {
                showingSecondView.toggle()
            }
            .padding()
        }
        .animation(.easeInOut, value: showingSecondView)
      }
}
Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 5

可以通过精确剪裁“抽屉”的容器来实现。这是可能方法的演示。

使用 Xcode 13.2 / iOS 15.2 进行测试(模拟器慢速动画处于开启状态,以获得更好的演示)

演示

var body: some View {
    VStack(spacing: 0) {
        Spacer()
        VStack {
            if showingSecondView {
                ZStack {
                    Color.green.opacity(0.25)
                    Text("Second View")
                }
                .transition(.move(edge: .bottom))
            } else {
                Color.clear // << replacement for transition visibility
            }
        }
        .frame(width: 300, height: 300)
        .animation(.easeInOut, value: showingSecondView)  // << animate drawer !!
        .clipped()            // << clip drawer area
        
        ZStack {
            Color.black.opacity(0.2)
            Text("First View")
        }
        .frame(width: 300, height: 300)

        Button("Animate In / Out") {
            showingSecondView.toggle()
        }
        .padding()
    }
}
Run Code Online (Sandbox Code Playgroud)