skip to Main Content

How can i get the Y offset of a a moving element at the same time while it’s moving?

This is the code that I’m tring the run:

import SwiftUI

struct testView: View {
    @State var showPopup: Bool = false
    
    var body: some View {
        ZStack {
            VStack {
                Button(action: {
                    self.showPopup.toggle()
                }) {
                    Text("show popup")
                }
                
                
                Color.black
                    .frame(width: 200, height: 200)
                    .offset(y: showPopup ? 0 : UIScreen.main.bounds.height)
                    .animation(.easeInOut)
                
            }
        }
    }
}

struct testView_Previews: PreviewProvider {
    static var previews: some View {
        testView()
    }
}

I want to get the Y value of the black squar when the button is clicked the squar will move to a 0 position however I want to detect when the squar did reach the 0 value how can i do that?

2

Answers


  1. SwiftUI doesn’t provide a callback with an animation completion, so there are two methods to accomplish detecting when the square has finished animating.

    Method 1: Using AnimatableModifier. Here’s a well-written Stack Overflow post on how to set that up.

    Method 2: Using a Timer to run after the animation has completed. The idea here is to create a scheduled timer that runs after the timer has finished.

    struct ContentView: View {
        @State var showPopup: Bool = false
        
        var body: some View {
            ZStack {
                VStack {
                    Button(action: {
                        // add addition here with specified duration
                        withAnimation(.easeInOut(duration: 1), {
                            self.showPopup.toggle()
                        })
    
                        // set timer to run after the animation's specified duration
                        _ = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { timer in
                            // run your completion code here eg.
                            withAnimation(.easeInOut(duration: 1)) {
                                self.showPopup.toggle()
                            }
                            timer.invalidate()
                        }
                    }) {
                        Text("show popup")
                    }
                    
                    Color.black
                        .frame(width: 200, height: 200)
                        .offset(y: showPopup ? 0 : UIScreen.main.bounds.height)
                }
            }
        }
    }
    
    Login or Signup to reply.
  2. Default animation duration (for those animations which do not have explicit duration parameter) is usually 0.25-0.35 (independently of where it is started & platform), so in your case it is completely safe (tested with Xcode 11.4 / iOS 13.4) to use the following approach:

    withAnimation(.spring()){
        self.offset = .zero
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            self.animationRunning = false
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search