'Move an UIView in a limited area of the screen using pan gesture

In my application, there is an UIView which should be moved in y direction when user pans in y direction on the super view within the given boundaries.

This is how it should work

enter image description here

This is my code

@IBOutlet weak var uiview: UIView!
// self.view is the supper view of uiview

var uiviewLastCenterPosition = CGPoint(x: 0, y: 0)
var lastTranslation = CGPoint(x: 0, y: 0)

override func viewDidAppear(_ animated: Bool) {
    self.uiviewLastCenterPosition = self.uiview.center
}

@IBAction func supperViewPan(_ sender: UIPanGestureRecognizer) {

    switch sender.state {

    case .began:
        break
    case .changed:

        let uiviewTop = self.uiview.frame.origin.y
        let uiviewBottom = self.uiview.frame.origin.y + self.uiview.frame.size.height

        let velocity = sender.velocity(in: self.view)

        if velocity.y > 0.0 { // down

            if uiviewBottom < 600{

                self.uiview.center.y = (self.uiviewLastCenterPosition.y) + sender.translation(in: self.view).y
                self.lastTranslation = sender.translation(in: self.view)
            }else{
                sender.setTranslation(self.lastTranslation, in: self.view)
            }

        }else if velocity.y < 0.0 { // up

            if uiviewTop > 100{

                self.uiview.center.y = (self.uiviewLastCenterPosition.y) + sender.translation(in: self.view).y
                self.lastTranslation = sender.translation(in: self.view)
            }else{
                sender.setTranslation(self.lastTranslation, in: self.view)
            }
        }
        break

    case .ended:

        self.uiviewLastCenterPosition = self.uiview.center
        break

    default:
        break
    }
}

All works perfect when user pans slowly. But when user pans fast, uiview goes beyond the boundaries.

enter image description here        enter image description here

Can someone please help me on this. I want to move the view exactly inside those boundaries. Any help would be highly appreciated.



Solution 1:[1]

You should clip the position before changing the position of the view which is self.uiview.center.y in your case. Look for the changes in the code.

@IBAction func supperViewPan(_ sender: UIPanGestureRecognizer) {
    switch sender.state {
    case .changed:
        let viewTop = self.slideView.frame.origin.y
        let viewBottom = self.slideView.frame.origin.y + self.slideView.frame.size.height
        let halfHeight = self.slideView.frame.height / 2 // here
        let velocity = sender.velocity(in: self.view)
        if velocity.y > 0.0 { // down
            if viewBottom < 600 {
                var displacedPosition = (self.uiviewLastCenterPosition.y) + sender.translation(in: self.view).y
                // changes here
                displacedPosition = displacedPosition > 600 - halfHeight ? 600 - halfHeight : displacedPosition 
                displacedPosition = displacedPosition < 100 + halfHeight ? 100 + halfHeight : displacedPosition 
                self.slideView.center.y = displacedPosition
                self.lastTranslation = sender.translation(in: self.view)
            } else {
                sender.setTranslation(self.lastTranslation, in: self.view)
            }
        } else if velocity.y < 0.0 { // up
            if viewTop > 100 {
                var displacedPosition = (self.uiviewLastCenterPosition.y) + sender.translation(in: self.view).y
                // changes here
                displacedPosition = displacedPosition < 100 + halfHeight ? 100 + halfHeight : displacedPosition
                displacedPosition = displacedPosition > 600 - halfHeight ? 600 - halfHeight : displacedPosition 
                self.slideView.center.y = displacedPosition
                self.lastTranslation = sender.translation(in: self.view)
            } else {
                sender.setTranslation(self.lastTranslation, in: self.view)
            }
        }
        break
    case .ended:
        self.uiviewLastCenterPosition = self.slideView.center
        break
    default:
        break
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rule_it_subir