如何在 SwiftUI 中为视图实现自定义转换

How do I implement a custom transition for a View in SwiftUI

我正在尝试实现一个过渡,使我的视图从侧面移入并通过变小而消失。 Apple 已经提供了一些 Transitions,但我如何自定义这些过渡? P.S。我正在使用 .transition 修饰符。

您可以按如下方式创建 AnyTransition 类型的计算变量:

static var moveAndFade: AnyTransition {
    let insertion = AnyTransition.move(edge: .trailing)
        .combined(with: .opacity)
    let removal = AnyTransition.scale
        .combined(with: .opacity)
    return .asymmetric(insertion: insertion, removal: removal)
}

您可能想查看 Apple 的 tutorial series

我想指出过渡动画存在一个错误。你应该能够通过这种方式得到你想要的东西:

struct ContentView: View {
    @State private var showView = false

    private var slideAndScale: AnyTransition {
        let insertion = AnyTransition.move(edge: .trailing)
        let removal = AnyTransition.scale
        return .asymmetric(insertion: insertion, removal: removal)
    }

    var body: some View {
        ZStack {
            Color.green
            if showView {
                Color.yellow
                    .transition(slideAndScale)
            }            
            Button(action: {
                withAnimation {
                    self.showView.toggle()
                }
            }) {
                self.showView ? Text("HIDE VIEW") : Text("SHOW VIEW")
            }
        }
    }
}

其中 Color.yellow 是使用自定义动画进出导航的视图。但是,如果您复制粘贴此代码,您会发现移除动画(在本例中为缩放动画)不起作用。这是 SwiftUI 的错误。要解决此问题,有一个解决方法:

struct ContentView: View {
    @State private var showView = false

    private var slideAndScale: AnyTransition {
        let insertion = AnyTransition.move(edge: .trailing)
        let removal = AnyTransition.scale
        return .asymmetric(insertion: insertion, removal: removal)
    }

    var body: some View {
        ZStack {
            Color.green
            VStack {
                if showView {
                    Color.yellow
                        .transition(slideAndScale)
                }
            }
            Button(action: {
                withAnimation {
                    self.showView.toggle()
                }
            }) {
                self.showView ? Text("HIDE VIEW") : Text("SHOW VIEW")
            }
        }
    }
}

if showView 块嵌入 VStack 中,移除动画将按预期运行。