Search code examples
iosswiftcore-animationuiviewpropertyanimator

interactive animation with panGesture iOS


I have a sheetView whose top edge is always centred at parent views center.

I am allowing it to drag vertically using pan gesture, and when gesture ends, I am animating sheetView back to center of parent view.

But I want to interact with the sheetView while it is still animating, and change its position vertically while panning, But I am not able to make it, it always finishes the current animation and then starts next animation.

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    sheetView.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height)
    middlePoint = CGPoint(x: view.bounds.midX, y: view.bounds.height)
    sheetView.center = middlePoint
}

@IBAction func handlePan(_ sender: UIPanGestureRecognizer) {
    let recognizer = sender
    let translation = recognizer.translation(in: self.view)

    if recognizer.state == .began {
        if animator.isRunning {
            animator.stopAnimation(true)
        }
        animator.addAnimations {
            self.sheetView.center = self.middlePoint
        }
        animator.pauseAnimation()
    } else if recognizer.state == .changed {
        self.sheetView.center.y += translation.y

    } else if recognizer.state == .ended || recognizer.state == .cancelled {
        if animator.isRunning {
            animator.stopAnimation(true)
        }
        animator.addAnimations {
            self.sheetView.center = self.middlePoint
        }
        animator.startAnimation()
    }

    recognizer.setTranslation(CGPoint.zero, in: self.view)
}

You can find entire project here: sheetView


Solution

  • Its because you are always applying animation. Even when you are moving the view, which is not required. That animation causes a break while you move the view.

        @IBAction func handlePan(_ sender: UIPanGestureRecognizer) {
            let recognizer = sender
            let translation = recognizer.translation(in: self.view)
    
            if recognizer.state == .began{
                    self.sheetView.center = self.middlePoint
            } else if recognizer.state == .changed{
                self.sheetView.center.y += translation.y
    
            }else if recognizer.state == .ended || recognizer.state == .cancelled{
                if animator.isRunning{
                    animator.stopAnimation(true)
                }
                animator.addAnimations {
                    self.sheetView.center = self.middlePoint
                }
                animator.startAnimation()
            }
    
            recognizer.setTranslation(CGPoint.zero, in: self.view)
    
        }