如何为视图生命周期事件(onAppear,onDisappear)制作可重用的修饰符?

时间:2020-07-25 09:35:15

标签: ios swift swiftui

我有一个常见的fadeInfadeOut动画,用于显示和消失视图:

struct ActiveView: View {
    @State var showCode: Bool = false
    @State var opacity = 0.0
    var body: some View {

    if self.showCode {
        Color.black.opacity(0.7)
            .onAppear{
                let animation = Animation.easeIn(duration: 0.5)
                    return withAnimation(animation) {
                        self.opacity = 1
                    }
            }
            .onDisappear{
                let animation = Animation.easeOut(duration: 0.5)
                    return withAnimation(animation) {
                        self.opacity = 0
                    }
            }
    }
    }
}

但是,我想在其他视图上使用这些相同的动画,所以我希望它是简单且可重用的,就像这样:

if self.showCode {
    Color.black.opacity(0.7)
        .fadeAnimation()
}

我该如何实现?

编辑:

尝试实现View扩展:

extension View {
    func fadeAnimation(opacity: Binding<Double>) -> some View {
        self.onAppear{
            let animation = Animation.easeIn(duration: 0.5)
                return withAnimation(animation) {
                    opacity = 1
                }
        }
        .onDisappear{
            let animation = Animation.easeOut(duration: 0.5)
                return withAnimation(animation) {
                    opacity = 0
                }
        }
    }
}

2 个答案:

答案 0 :(得分:2)

您尝试做的事情已经存在,并命名为 opacity transition ,它是用一个修饰符编写的。

这是一个演示:

demo

struct ActiveView: View {
    @State var showCode: Bool = false
    var body: some View {
        ZStack {
            if self.showCode {
                Color.black.opacity(0.7)
                    .transition(AnyTransition.opacity.animation(.default))
            }
            Button("Demo") { self.showCode.toggle() }
        }.frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

答案 1 :(得分:2)

您要实现的功能已经是SwiftUI的Animation和Transition修改器的一部分。

因此,您可以将.transition修饰符添加到您的任何Views中,它将修饰其插入和删除动画。

if self.showCode {
    Color.black.opacity(0.7)
        .transition(AnyTransition.opacity.animation(.easeInOut(duration: 0.5)))
}

您可以使用多种不同的过渡,例如.slide.scale.offset等。有关过渡here的更多信息。

您甚至可以使用不同的操作来创建自定义过渡,以进行插入和移除。根据您的情况,可以使用不同的动画曲线。

extension AnyTransition {
    static var fadeTransition: AnyTransition {
        .asymmetric(
            insertion: AnyTransition.opacity.animation(.easeIn(duration: 0.5)),
            removal: AnyTransition.opacity.animation(.easeOut(duration: 0.5))
        )
    }
}

并像这样使用它:

if self.showCode {
    Color.black.opacity(0.7)
        .transition(.fadeTransition)
}

希望这对您有帮助!