swiftuiimageviewuikit-dynamicsuidynamicanimatoruigravitybehavior

How to make UIImageView animation wait for dynamicAnimator behavior to finish to start animating


I'm working on an animation for an app, where a shoe box falls from the top of the screen and lands on a pedestal, then the box opens.

I was wondering if there was any way to make the animation for opening the box to wait for the box to get settled on the pedestal before performing the opening animation?

Here's my code:

//dropping box from off screen and having it stop on the pedestal
    dynamicAnimator = UIDynamicAnimator(referenceView: self.view)
    //gravity
    gravityBehavior = UIGravityBehavior(items: [shoeBoxImage])
    dynamicAnimator.addBehavior(gravityBehavior)
    //collision
    collisionBehavior = UICollisionBehavior(items: [shoeBoxImage])
    collisionBehavior.addBoundary(withIdentifier: "Pedestal" as NSCopying, from: CGPoint(x: view.frame.minX, y: 545), to: CGPoint(x: view.frame.maxX, y: 545))
    dynamicAnimator.addBehavior(collisionBehavior)
    //bouncing effect
    bouncingBehavior = UIDynamicItemBehavior(items: [shoeBoxImage])
    bouncingBehavior.elasticity = 0.40
    dynamicAnimator.addBehavior(bouncingBehavior)
    
    //Load Data Here
    Task {
        Shoes = try await queryShoes()
    }
    
    //Opening the box
    shoeBoxImage.shoeBox.animationImages = boxOpeningAnimation
    shoeBoxImage.shoeBox.animationDuration = 1.0
    shoeBoxImage.shoeBox.animationRepeatCount = 1
    shoeBoxImage.shoeBox.contentMode = .scaleAspectFit
    shoeBoxImage.shoeBox.startAnimating()
    shoeBoxImage.shoeBox.image = UIImage(named: "frame11")

Is there any way to do this besides checking for the image view's center position in order to set a bool, then using the said bool to determine whether or not to start animating? If so, could someone please explain how to do so? It would be very much appreciated.


Solution

  • There is a delegate method that you can use to know when the dynamic animator pauses.

    Assign an object as a delegate to the animator

    dynamicAnimator.delegate = self

    and then implement the dynamicAnimatorDidPause method.

    extension ViewController: UIDynamicAnimatorDelegate {
        public func dynamicAnimatorDidPause(_ animator: UIDynamicAnimator) {
            //Start your box opening animation here...
        }
    }
    

    Below is an excerpt from UIDynamicAnimator Apple Developer Documentation.

    All types of dynamic animators share the following characteristics:

    You can implement a delegate to respond to changes in animator pause/resumption status, using the dynamicAnimatorDidPause(_:) and dynamicAnimatorWillResume(_:) methods of the UIDynamicAnimatorDelegate protocol.


    You have to note here that the animator might not call dynamicAnimatorDidPause method even though it would seem that the animations have stopped. This could be due to some minuscule changes in parameters of the animated object that is not necessarily visible to the eye. If that happens, you have to consider changing some animation properties so that the animation stops quickly without wiggling around.