In this sample app, I have a title in the top left of the screen, and a button in the bottom right. I'm using stacks and spacers to align them.
Currently, when you press the button, it animates up/left a little. But I want the button to animate to the exact center of the screen (or safe area), regardless of device or button size. The code is shown below, along with images of the start and end of the animation I want.
struct ContentView: View {
    @State var buttonIsMoved = false
    var body: some View {
        VStack {
            HStack {
                Text("Title")
                    .font(.largeTitle)
                Spacer()
            }
            Spacer()
            HStack {
                Spacer()
                // This is the button I want to animate to the center
                Button(action: {
                    self.buttonIsMoved.toggle()
                }) {
                    Text("This is a button")
                        .foregroundColor(.black)
                        .padding(16)
                        .background(Color.green)
                }
                    // Currently I'm just using fixed offset values,
                    // but I want it to move to the actual center of the screen
                    .offset(buttonIsMoved ? CGSize(width: -50, height: -200) : .zero)
                    .animation(.easeInOut)
            }
        }
        .padding(32)
    }
}
Start of animation
End of animation
If I use .offset(), I don't know how to calculate the distance between the button's center and the center of the screen. I've also tried to use .position() but it's based on the parent view, which in this case is an HStack below the title, so it wouldn't be centered within the whole screen. I've also heard of GeometryReader, but I can't figure out how to use it for this purpose.
Here is possible solution - no hardcoding, based on SwiftUI native layout engine.
Tested with Xcode 11.4 / iOS 13.4

struct DemoAnimateLayout: View {
    @State var buttonIsMoved = false
    var body: some View {
        ZStack {
            VStack {
                HStack {
                    Text("Title")
                        .font(.largeTitle)
                    Spacer()
                }
                Spacer()
            }
            VStack {
                if !buttonIsMoved {  // <<      here !!
                    Spacer()
                }
                HStack {
                    if !buttonIsMoved {  // <<     here !!
                        Spacer()
                    }
                    // This is the button I want to animate to the center
                    Button(action: {
                        self.buttonIsMoved.toggle()
                    }) {
                        Text("This is a button")
                            .foregroundColor(.black)
                            .padding(16)
                            .background(Color.green)
                    }
                }
            }
            .animation(.easeInOut)  // << animate container layout !!
        }.padding(32)
    }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With