简体   繁体   English

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

[英]How to clip a view while using a SwiftUI .move transition / animation

I'm trying to animate in a view and make it appear as if it's a sort of drawer opening from another view.我试图在一个视图中制作动画,让它看起来好像是从另一个视图打开的一种抽屉。 This is all fine except if the first view is not opaque.这一切都很好,除非第一个视图不是不透明的。 It appears that you can see the animating view the moment it begins animating.您似乎可以在动画开始动画的那一刻看到动画视图。 Is there a way to clip this so it appears that the view is growing from the top of the bottom view?有没有办法剪辑这个,所以看起来视图是从底部视图的顶部增长的?

Even without opacity this is an issue if where you're animating in from isn't a covered (demoed in second gif)即使没有不透明度,如果您从中制作动画的位置没有被覆盖,这也是一个问题(在第二个 gif 中演示)

动画示例 其他动画示例

Sample Code:示例代码:

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

It is possible to do by clipping exact container of 'drawer'.可以通过剪裁“抽屉”的确切容器来完成。 Here is a demo of possible approach.这是一个可能的方法的演示。

Tested with Xcode 13.2 / iOS 15.2 (Simulator slow animation is ON for better demo)使用 Xcode 13.2 / iOS 15.2 测试(模拟器慢 animation 为 ON 以获得更好的演示)

演示

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

backup 备份

Here a way for you:这里给你一个方法:

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

    var body: some View {
        
        VStack(spacing: 0) {
            Spacer()
            
            ZStack {
                Color.green.opacity(0.25).cornerRadius(20)
                Text("Second View")
            }
            .frame(width: 300, height: 300)
            .offset(y: isSecondViewPresented ? 0 : 300)
            .clipShape(RoundedRectangle(cornerRadius: 20))
            
            
            ZStack {
                Color.black.opacity(0.1).cornerRadius(20)
                Text("First View")
            }
            .frame(width: 300, height: 150)
            
            Button("Animate In / Out") {
                isSecondViewPresented.toggle()
            }
            .padding()
        }
        .animation(.easeInOut, value: isSecondViewPresented)
        
    }

}

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM