I have this code:
Group{
if self.done{
Image(systemName: "plus").font(.system(size: 40)).foregroundColor(.gray)
.padding().overlay(Circle().stroke(Color.gray, lineWidth: 3)).opacity(0.6)
}
else{
Button(action: {self.showSearchTrash = 1}){
Image(systemName: "plus").font(.system(size: 40)).foregroundColor(green)
.padding().overlay(Circle().stroke(green, lineWidth: 3).scaleEffect(1+self.animationAmount).animation(Animation.easeInOut(duration: 1).repeatForever(autoreverses: true)).onAppear {self.animationAmount = 0.1})
}
}
}.padding(.bottom, 5)
And the intention is that if self.done
is false
, the circle on the plus button will expand and contract indefinitely.
This works. However, if I use a toggle to set self.done
to be true
and then turn it back to false
, the animation no longer occurs. I know that the issue is not with the toggle, because it does return to being green.
Also, the lack of .
before green
is intentional - I defined a specific Color green
.
Any idea why the animation stops working/how to fix this?
You can specify Animation
in the withAnimation
block and create separate functions for starting/stopping the animation.
Here is a possible solution:
struct ContentView: View {
@State private var done = false
@State private var animationAmount: CGFloat = 0
var body: some View {
VStack {
Toggle("Done", isOn: $done)
plusImage
.opacity(done ? 0.6 : 1)
.foregroundColor(done ? .gray : .green)
}
.onAppear(perform: startAnimation)
.onChange(of: done) { done in
if done {
stopAnimation()
} else {
startAnimation()
}
}
}
var plusImage: some View {
Image(systemName: "plus")
.font(.system(size: 40))
.padding()
.overlay(
Circle()
.stroke(Color.gray, lineWidth: 3)
.scaleEffect(1 + animationAmount)
)
}
}
private extension ContentView {
func startAnimation() {
withAnimation(Animation.easeInOut(duration: 1).repeatForever()) {
animationAmount = 0.1
}
}
func stopAnimation() {
withAnimation {
animationAmount = 0
}
}
}
Actually works fine as-is with Xcode 12.1 / iOS 14.1, so you might observe either bug of new iOS version or result of some other code.
Anyway, I would added turn-offs scaling on button disappear:
Button(action: {}){
Image(systemName: "plus").font(.system(size: 40)).foregroundColor(green)
.padding().overlay(Circle().stroke(green, lineWidth: 3).scaleEffect(1+self.animationAmount).animation(Animation.easeInOut(duration: 1).repeatForever(autoreverses: true)))
}
.onAppear {self.animationAmount = 0.1} // << put here !!
.onDisappear {self.animationAmount = 0} // << add this !!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.