Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In SwiftUI, how do I animate a view from its current position to the center of the screen?

Tags:

ios

swift

swiftui

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.

like image 718
Milo Wyner Avatar asked Oct 16 '25 04:10

Milo Wyner


1 Answers

Here is possible solution - no hardcoding, based on SwiftUI native layout engine.

Tested with Xcode 11.4 / iOS 13.4

demo

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)
    }
}
like image 65
Asperi Avatar answered Oct 17 '25 18:10

Asperi