Button animation bug: repeated movement behaviour

Hi,
I've created an effect that after clicking on the "Hello, world!" button, it has to move (first move is when the user taps on it), and then it has to move again, but this time without any interaction, and it does. But the problem is that when I click again on it, it goes back and then returns to the same position, I can't understand how to solve this issue. This is my code:

import SwiftUI
public struct ContentView: View {
@State var xPos: CGFloat = 300
@State var yPos: CGFloat = 400
@State var size: CGFloat = 120
public var body: some View {
ZStack {
Image("background")
.resizable()
.frame(width: 700, height: 500)
.padding()
.overlay {
Button(action: {
xPos = 170
yPos = 310
size = 60
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
xPos = 700
}
}) {
Text("Hello, world!")
.font(.system(size: size))
.position(x: xPos, y: yPos)
}
.animation(.spring)
}
}
}
}

Can anyone help me?

Thanks in advance!

What's happening is you've set your initial position and size at the top, with:

@State var xPos: CGFloat = 300
@State var yPos: CGFloat = 400
@State var size: CGFloat = 120

and so SwiftUI draws your Button at a font size of 120, and at (300, 400).

When you tap the button you change the size to 60, and the position to (170, 310).

Then, one second later, you change the x position to 700, so the button moves to (700, 310) and remains at size 60.

Your variables are now: xPos = 700, yPos = 310, size = 60.

When you press it again, all the code is doing is changing the size to 60 (it's already 60), and the position to (170, 310), then it moves the x position to 700 after one second. This will keep happening every time you press the button, because it's stuck with those values.

What position do you want the button to go back to, and at what size? Those are the values you need to plug into the DispatchQueue... block. So...

Back to the starting position:

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
xPos = 300
yPos = 400
size = 120
}

To x position 700, then back to the start, all within one second? Try this:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
xPos = 700
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
xPos = 300
yPos = 400
size = 120
}

Also, to get rid of the deprecation warning, use something like:

.animation(.spring(duration: 1), value: [xPos, yPos, size])
Button animation bug: repeated movement behaviour
 
 
Q