Reputation: 39
I'm having some trouble layering iOS animations for my video recoding button. I've modeled it after other standard recording buttons and I'd like for it to begin as a solid circle and then on press, transform to a rounded rectangle where its opacity pulses.
The issue is that I've ordered the animations in a way such that their all applied at the same time.
https://i.sstatic.net/N8lzx.jpg
I've tried reordering these animations but can't figure out which ordering with achieve the scope I want.
import SwiftUI
struct ContentView: View {
@State var recordComplete = false
@State private var rCorner: CGFloat = 100
@State private var rWidth: CGFloat = 70
@State private var rHeight: CGFloat = 70
@State private var opacityVal = 1.0
var body: some View {
HStack{
Button(action: {
self.rCorner = self.rCorner == 100 ? 12 : 100
self.rWidth = self.rWidth == 70 ? 45 : 70
self.rHeight = self.rHeight == 70 ? 45 : 70
self.recordComplete.toggle()
}) {
ZStack{
Circle()
.stroke(Color.red, lineWidth: 6)
.frame(width:85, height: 85)
RoundedRectangle(cornerRadius: rCorner)
.fill(Color.red)
.frame(width: rWidth, height: rHeight)
.opacity(opacityVal)
.animation(Animation.easeInOut(duration: 1).repeatForever(autoreverses: true)).onAppear{ self.opacityVal = 0.3 }
}
.padding(.vertical, 25)
}
}.animation(.spring(response: 0.5, dampingFraction: 2, blendDuration: 0.5))
}
}
Thank you as always for the help with this issue!
Upvotes: 1
Views: 59
Reputation: 257543
Here is a possible solution - the main idea is to separate animations by value and make them serial. Tested with Xcode 12 / iOS 14
struct ContentView: View {
@State var recordComplete = false
@State private var rCorner: CGFloat = 100
@State private var rWidth: CGFloat = 70
@State private var rHeight: CGFloat = 70
@State private var opacityVal = 1.0
var body: some View {
HStack{
Button(action: {
self.rCorner = self.rCorner == 100 ? 12 : 100
self.rWidth = self.rWidth == 70 ? 45 : 70
self.rHeight = self.rHeight == 70 ? 45 : 70
self.recordComplete.toggle()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.opacityVal = self.recordComplete ? 0.3 : 1.0
}
}) {
ZStack{
Circle()
.stroke(Color.red, lineWidth: 6)
.frame(width:85, height: 85)
RoundedRectangle(cornerRadius: rCorner)
.fill(Color.red)
.frame(width: rWidth, height: rHeight)
.opacity(opacityVal)
.animation(
self.recordComplete ?
Animation.easeInOut(duration: 1).repeatForever(autoreverses: true) :
Animation.default,
value: opacityVal)
}
.padding(.vertical, 25)
}
}.animation(.spring(response: 0.5, dampingFraction: 2, blendDuration: 0.5), value: rCorner)
}
}
Upvotes: 1