Search code examples
swiftuikituipangesturerecognizer

how can i decrease scale as i am swipping upward in swift


i want to decrease scale of uiview as swiping upwards, i want the same animation for closing app like in ios 12 or 13.

class ViewController: UIViewController {
    @IBOutlet weak var myView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
       let panGesture = UIPanGestureRecognizer(target: self, action: #selector(didPanningFromBottom))
        
        myView.addGestureRecognizer(panGesture)
        panGesture.delegate = self
    }
    @objc func didPanningFromBottom(recognizer: UIPanGestureRecognizer){
        if recognizer.state == .began {
            print("began")
        }
        else if recognizer.state == .changed {
            UIView.animate(withDuration: 0.1, delay: 0.25, options: .curveEaseOut) {
                self.myView.transform = CGAffineTransform(scaleX: 0.25, y: 0.25 )
            }

        }
    }
}

Solution

  • You can do something like this.

    Assuming the rest of your code is intact just swap didPanningFromBottom.

    Basically there are two things you need to do. First track the drag operation and just move along the view with the finger, scaling it a bit if you want. Second, on release, determine if you should animate away the view or let it bounce back. In my code I check both the velocity and the distance of the release point. You might want to modify the exact values.

    You probably also want to check for .cancel case to always move back to start position.

    @objc func didPanningFromBottom(recognizer: UIPanGestureRecognizer){
        let yPosition = recognizer.translation(in: view).y
        let yVelocity = recognizer.velocity(in: view).y
    
        if recognizer.state == .began {
    
        } else if recognizer.state == .changed {
    
            // Scale down a small amount
            let scale: CGFloat = 1.0 - abs(yPosition / 2000)
            
            myView.transform = CGAffineTransform.identity
                .translatedBy(x: 0, y: yPosition)
                .scaledBy(x: scale, y: scale)
    
        } else if recognizer.state == .ended {
    
            // If either have a minimum velocity or release beyond a fixed point
            if yVelocity < -200 || (yVelocity <= 0 && yPosition < 400) {
    
                UIView.animate(withDuration: 0.25) {
                    self.myView.transform = CGAffineTransform.identity.translatedBy(x: 0, y: -self.view.bounds.size.height / 2 - self.myView.bounds.size.height / 2)
                    self.myView.alpha = 0
                }
            } else {
                // Move it back to start
                UIView.animate(withDuration: 0.25) {
                    self.myView.transform = CGAffineTransform.identity
                }
            }
        }
    }