SwiftUI:如何保持动画隐藏和显示按钮(视图)?

时间:2021-06-08 12:29:51

标签: animation swiftui

在我的应用程序中,我有一个按钮,它的动画表明该应用程序当前正在执行与该按钮关联的功能。

一切正常,直到有必要在屏幕上隐藏/显示按钮(或包含它的视图)。 当按钮返回屏幕时,按钮动画停止工作。我明白为什么会发生这种情况(没有需要动画的状态变化),但我不明白它是如何容易解决的((

最终,无论按钮隐藏/显示多少次,我都希望按钮动画始终仅取决于动画显示的状态。

struct ContentView: View {

@State private var animationOn = false
@State private var showButton = true

let buttonAnimation = Animation.easeIn(duration: 1).repeatForever(autoreverses: false)

var body: some View {
    
    VStack {
        
        Toggle("Show button", isOn: $showButton)
            .padding()
        
        if showButton {
            
            Image(systemName: "face.smiling")
                .imageScale(.large)
                .overlay(
                    Circle()
                        .stroke(Color.blue, lineWidth: animationOn ? 5 : 0)
                        .scaleEffect(animationOn ? 2 : 1)
                        .opacity(animationOn ? 0 : 1)
                        .animation(animationOn ? buttonAnimation : Animation.default)
                )
                .onTapGesture {
                    animationOn.toggle()
                }

        }
        
        Text("animation is \(animationOn ? "on" : "off")")
            .padding()
        
    }
    
}

}

showing problem

1 个答案:

答案 0 :(得分:0)

我自己找到了解决方案)) 正如我已经写过的,关键是当按钮出现在屏幕上时,需要进行一些更改才能产生动画。 所需的操作在代码的注释中注明。

struct ContentView: View {

@State private var animationOn = false
@State private var showButton = true

let buttonAnimation = Animation.easeIn(duration: 1).repeatForever(autoreverses: false)

//1. declare properties for animation
@State private var lineWithForAnimation: CGFloat = 2
@State private var scaleEffectForAnimation: CGFloat = 2
@State private var opacityForAnimation: Double = 0

var body: some View {
    
    VStack {
        
        Toggle("Show button", isOn: $showButton)
            .padding()
        
        if showButton {
            
            Image(systemName: "face.smiling")
                .imageScale(.large)
                .overlay(
                    Circle()
                        //2. use properties for animation
                        .stroke(Color.blue, lineWidth: lineWithForAnimation)
                        .scaleEffect(scaleEffectForAnimation)
                        .opacity(opacityForAnimation)
                        .animation(animationOn ? buttonAnimation : Animation.default)
                )
                .onTapGesture {
                    animationOn.toggle()
                    changeAnimatedProperties()
                }
                //3. change properties for animation onAppear
                .onAppear{
                    changeAnimatedProperties()
                }
                //4. reset properties for animation onDisappear
                .onDisappear{
                    resetAnimatedProperties()
                }

        }
        
        Text("animation is \(animationOn ? "on" : "off")")
            .padding()
        
    }
    
}

func changeAnimatedProperties() {
    lineWithForAnimation = animationOn ? 2 : 0
    scaleEffectForAnimation = animationOn ? 2 : 1
    opacityForAnimation = animationOn ? 0 : 1
}

func resetAnimatedProperties() {
    lineWithForAnimation = 0
    scaleEffectForAnimation = 1
    opacityForAnimation = 1
}

}