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