So I am trying to make some text fade in and out to give a pulsate type effect, this is the code I have now:
struct SignInView: View {
@State private var opacity: Double = 0.0
@State private var pulseDown: Bool = false
var body: some View {
VStack(alignment: .center) {
Spacer()
Button(action: {
AppDelegate.signInWithGoogle()
}, label: {
Text("Sign In")
.foregroundColor(Color.green)
.opacity(opacity)
})
Spacer()
}
.padding()
.onAppear {
self.pulsateText()
}
}
private func pulsateText() {
DispatchQueue.init(label: "Pulse").asyncAfter(deadline: .now() + 0.01) {
if self.pulseDown {
self.opacity -= 0.02
} else {
self.opacity += 0.02
}
if self.opacity > 1 {
self.pulseDown = true
} else if self.opacity < 0.1 {
self.pulseDown = false
}
self.pulsateText()
}
}
}
It does exactly what I want and looks good, but I can't help but feel that an infinite recursive loop is not the right way to be doing it. I suppose I could make an infinite while instead of the infinite recursion, though that still seem not ideal. Is there a better way to achieve this?
There is an easier more SwiftUI-like way. It works by using an Animation
's repeatForever(autoreverses:)
method:
struct SignInView: View {
@State private var visible = true
var body: some View {
VStack {
Spacer()
Button(action: {
print("Sign in with Google")
// AppDelegate.signInWithGoogle()
}, label: {
Text("Sign In")
.foregroundColor(Color.green)
.opacity(visible ? 1 : 0)
})
Spacer()
}
.padding()
.onAppear(perform: pulsateText)
}
private func pulsateText() {
withAnimation(Animation.easeInOut.repeatForever(autoreverses: true)) {
visible.toggle()
}
}
}