Swift: move UIView on slide gesture

31,305

Solution 1

Finally did it like below.

let gesture = UIPanGestureRecognizer(target: self, action: Selector("wasDragged:"))
slideUpView.addGestureRecognizer(gesture)
slideUpView.userInteractionEnabled = true
gesture.delegate = self

The following function is called when the gesture is detected, (here I am restricting the view to have a maximum centre.y of 555, & I'm resetting back to 554 when the view moves past this point)

func wasDragged(gestureRecognizer: UIPanGestureRecognizer) {
    if gestureRecognizer.state == UIGestureRecognizerState.Began || gestureRecognizer.state == UIGestureRecognizerState.Changed {
        let translation = gestureRecognizer.translationInView(self.view)
        print(gestureRecognizer.view!.center.y)
        if(gestureRecognizer.view!.center.y < 555) {
            gestureRecognizer.view!.center = CGPointMake(gestureRecognizer.view!.center.x, gestureRecognizer.view!.center.y + translation.y)
        }else {
            gestureRecognizer.view!.center = CGPointMake(gestureRecognizer.view!.center.x, 554)
        }

        gestureRecognizer.setTranslation(CGPointMake(0,0), inView: self.view)
    }

}

Solution 2

You probably want to use a UIPanGestureRecognizer.

let gesture = UIPanGestureRecognizer(target: self, action: Selector("wasDragged:"))
customView.addGestureRecognizer(gesture)
gesture.delegate = self

And to drag the object only along the y-axis:

func wasDragged(gesture: UIPanGestureRecognizer) {
    let translation = gesture.translationInView(self.view)

    // Use translation.y to change the position of your customView, e.g.
    customView.center.y = translation.y // Customize this.
}

Solution 3

Swift 4:

@objc func wasDragged(_ gestureRecognizer: UIPanGestureRecognizer) {

    if gestureRecognizer.state == UIGestureRecognizer.State.began || gestureRecognizer.state == UIGestureRecognizer.State.changed {

        let translation = gestureRecognizer.translation(in: self.view)
        print(gestureRecognizer.view!.center.y)

        if(gestureRecognizer.view!.center.y < 555) {

            gestureRecognizer.view!.center = CGPoint(x: gestureRecognizer.view!.center.x, y: gestureRecognizer.view!.center.y + translation.y)

        }else {
            gestureRecognizer.view!.center = CGPoint(x:gestureRecognizer.view!.center.x, y:554)
        }
        gestureRecognizer.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
    }
}

Call

let gesture = UIPanGestureRecognizer(target: self, action: self.wasDragged(gestureRecognizer:))
customView.addGestureRecognizer(gesture)
gesture.delegate = self

Solution 4

Move view anywhere in Swift 3

let panGesture = UIPanGestureRecognizer(target: self, action: #selector(dragged(gestureRecognizer:)))
demoView.isUserInteractionEnabled = true
demoView.addGestureRecognizer(panGesture)

Function

@objc func dragged(gestureRecognizer: UIPanGestureRecognizer) {
    if gestureRecognizer.state == UIGestureRecognizerState.began || gestureRecognizer.state == UIGestureRecognizerState.changed {
        let translation = gestureRecognizer.translation(in: self.view)
        gestureRecognizer.view!.center = CGPoint(x: gestureRecognizer.view!.center.x + translation.x, y: gestureRecognizer.view!.center.y + translation.y)
        gestureRecognizer.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
    }
}

Solution 5

This is how you really do it like the news view in the Stocks app

First add 2 constraints in Storyboard to the sliding view, one for it's state when it's fully opened and one for when it's closed. Don't forget to leave one of the constraints disabled / not installed so that your view will look opened or closed when the scene is reached. Reference them in your code

@IBOutlet weak var optionsOpenedConstraint: NSLayoutConstraint!
@IBOutlet weak var optionsVisiableConstraint: NSLayoutConstraint!

now add the UIPanGestureRecognizer to your view in the viewDidLoad function.

let gesture = UIPanGestureRecognizer(target: self, action: #selector(type(of: self).wasDragged(gestureRecognizer:)))
    optionsView.addGestureRecognizer(gesture)

finally add this callback and 2 functions:

@objc func wasDragged(gestureRecognizer: UIPanGestureRecognizer) {
    let distanceFromBottom = screenHeight - gestureRecognizer.view!.center.y
    if gestureRecognizer.state == UIGestureRecognizer.State.began || gestureRecognizer.state == UIGestureRecognizer.State.changed {
        optionsOpenedConstraint.isActive = false
        optionsVisiableConstraint.isActive = false
        let translation = gestureRecognizer.translation(in: self.view)
        if((distanceFromBottom - translation.y) < 100) {
            gestureRecognizer.view!.center = CGPoint(x: gestureRecognizer.view!.center.x, y: gestureRecognizer.view!.center.y + translation.y)
            gestureRecognizer.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
        }

    }
    if gestureRecognizer.state == UIGestureRecognizer.State.ended{
        if distanceFromBottom > 6{
            openOptionsPanel()
        }else{
            closeOptionsPanel()
        }
    }
}
func openOptionsPanel(){
    optionsOpenedConstraint.isActive = true
    optionsVisiableConstraint.isActive = false
    UIView.animate(withDuration: 0.5) {
        self.view.layoutIfNeeded()
    }
}

func closeOptionsPanel(){
    optionsOpenedConstraint.isActive = false
    optionsVisiableConstraint.isActive = true
    UIView.animate(withDuration: 0.5) {
        self.view.layoutIfNeeded()
    }
}

and voalá enter image description here

Share:
31,305
Nagendra Rao
Author by

Nagendra Rao

~10 years of experience building top quality applications (Web apps, Backend Systems &amp; Mobile apps) from scratch. Expert in iOS Swift &amp; Node.JS Most recent work: Koo -&gt; https://apps.apple.com/us/app/id1515425674 ONE Championship -&gt; https://apps.apple.com/us/app/id1351178131 Scroll News, ScoopWhoop, WickedRide etc in the past

Updated on March 30, 2020

Comments

  • Nagendra Rao
    Nagendra Rao about 4 years

    I am trying to move a UIView on slide up gesture from its initial position to a fixed final position. The image should move with the hand gesture, and not animate independently.

    I haven't tried anything as I have no clue where to start, which gesture class to use.

    enter image description here