30

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

Nagendra Rao
  • 7,016
  • 5
  • 54
  • 92

7 Answers7

33

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)
    }

}
Nagendra Rao
  • 7,016
  • 5
  • 54
  • 92
13

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.
}
xoudini
  • 7,001
  • 5
  • 23
  • 37
9

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
Neeraj Joshi
  • 721
  • 9
  • 26
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
3

Update for Swift 3.x

When assigning the selector, the syntax has changed and now requires #selector

let gesture = UIPanGestureRecognizer(target: self, action: #selector(navViewDragged(gesture:)))

    self.navLayoutView.addGestureRecognizer(gesture)
    self.navLayoutView.isUserInteractionEnabled = true
    gesture.delegate = self

Function implementation:

func navViewDragged(gesture: UIPanGestureRecognizer){
     //Code here
}
1

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)
    }
}
Manish Mahajan
  • 2,062
  • 1
  • 13
  • 19
1

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

Saleh Altahini
  • 373
  • 2
  • 12
-1
@IBAction func handlePanGesture(_ recognizer: UIPanGestureRecognizer) {

    if MainView.bounds.contains(mainImage.frame) {
        let recognizerCenter = recognizer.location(in:  MainView)

        mainImage.center = recognizerCenter
    }

    if MainView.bounds.intersection(mainImage.frame).width > 50 && MainView.bounds.intersection(mainImage.frame).height > 0 {
        let recognizerCenter = recognizer.location(in: MainView)
        print(recognizerCenter)
        mainImage.center = recognizerCenter
    }

}

@IBAction func handlePinchGesture(_ recognizer: UIPinchGestureRecognizer) {

    mainImage.transform = mainImage.transform.scaledBy(x: recognizer.scale, y: recognizer.scale)
    recognizer.scale = 1.0
}

@IBAction func handleRotateGesture(_ recognizer: UIRotationGestureRecognizer) {

    mainImage.transform = mainImage.transform.rotated(by: recognizer.rotation)
    recognizer.rotation = 0.0

}