2

This is the code I have written so far to change the position of the view when dragged.

The view changes its center point when the UIPanGestureRecognizer is either changed or began and that happen when I let go the gesture. I do not want that. I want it to go along with my drag like what the Notification Center and Control Center does.

Thanks in advance for the help.

class ViewController: UIViewController {

let maxY = UIScreen.main.bounds.height
lazy var slideUpView: UIView = {
    let view = UIView(frame: CGRect(x: 0, y: maxY - 295, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height / 3 ))
    view.backgroundColor = .green
    return view
}()


lazy var redImageView: UIView = {
    let view = UIView(frame: CGRect(x: 0, y: maxY - 295, width: UIScreen.main.bounds.width, height: slideUpView.frame.height / 2 ))
    view.backgroundColor = .red
    return view
}()

override func viewDidLoad() {
    super.viewDidLoad()

    print("MaxX: \(UIScreen.main.bounds.maxX)")
    print("Max Hight: \(UIScreen.main.bounds.height)")
    print("MaxY: \(UIScreen.main.bounds.maxY)")
    print("Max width: \(UIScreen.main.bounds.width)")
    // MARK: add the views as subview
    let viewsArray = [slideUpView, redImageView]
    viewsArray.forEach{view.addSubview($0)}
    // Add a UIPanGestureRecognizer to it
    viewsArray.forEach {createPanGestureRecognizer(targetView: $0)}
}

// The Pan Gesture
func createPanGestureRecognizer(targetView: UIView) {
    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(recognizer:)))
    panGesture.maximumNumberOfTouches = 1
    targetView.addGestureRecognizer(panGesture)
}

@objc func handlePanGesture(recognizer: UIPanGestureRecognizer) {
    if recognizer.state == UIGestureRecognizerState.began || recognizer.state == UIGestureRecognizerState.changed {
        let translation = recognizer.translation(in: self.view)
        print(recognizer.view!.center.y)
        let newPos = CGPoint(x:recognizer.view!.center.x + translation.x, y: recognizer.view!.center.y + translation.y)
        if insideDraggableArea(newPos) {
            guard let targetedView = recognizer.view else {
                print("Error: No View to handle")
                return
            }
            targetedView.center.y = newPos.y
            recognizer.setTranslation(.zero, in: targetedView)
        }
    }
}

private func insideDraggableArea(_ point : CGPoint) -> Bool {
    return  // point.x > 50 && point.x < 200 &&
        point.y > (maxY * 0.27) && point.y <= maxY
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        let position = touch.location(in: view)
        print(position)
    }
  }
 }
Mohsen
  • 193
  • 1
  • 12
  • I dont understand what is wrong right now.. explain yourself a bit better – Milan Nosáľ Mar 01 '18 at 17:19
  • I do not see anything wrong with my description. However, the portion of the UIView changes after the gesture reaches a new point and you have to left your finger off the screen. But If you swipe up the control center on your iPhone you will see that it will follow your finger very smoothly. – Mohsen Mar 01 '18 at 17:25
  • 1
    Just use a CABasicAnimation to change the view layer position – Leo Dabus Mar 01 '18 at 17:26
  • Simple, when the pan gesture has ended and the view hasn't, for example traveled a certain distance, animate the position of that view back to its origin. – trndjc Mar 01 '18 at 17:27
  • would that animate the new points of something like this in real time or does it have to set let say from point A = 100 to B = 350. the is an output of the points ``` 363.333333333333 364.666661580404 369.333333333333 369.333333333333 376.333333333333 381.999989827474 384.333333333333 388.666661580404 391.333333333333 400.666661580404 408.333333333333 420.666661580404 428.333333333333 435.666661580404 ```` – Mohsen Mar 01 '18 at 17:28
  • 1
    There is already a very detailed answer on how to approach the problem here https://stackoverflow.com/a/48196975/2303865 it shows how to rotate but you can adapt the answer to just move. Give it a try if you still have issues edit your question post your attempt and let me know – Leo Dabus Mar 01 '18 at 17:29
  • Thanks Leo Dabus – Mohsen Mar 01 '18 at 17:30
  • 1
    Nate already mentioned it, the code you list here seems to work, you need to provide better description of what your problem really is.. from the question it seems that the view does not move until you lift your finger, but the code is working normally – Milan Nosáľ Mar 01 '18 at 17:32
  • 1
    This code works fine. Create a blank project and include this code and you'll see it drags without problem. You must have something else going on that you haven't included here. We need [MCVE](https://stackoverflow.com/help/mcve). Keep adding more of your actual code to your blank project until you can reproduce the problem. Sure, there is plenty of curious stuff here (e.g. why did you specify a delegate when you don't have any delegate methods? you generally do either gesture recognizer or touches methods, but not both; etc.), but this doesn't manifest the bug you report. – Rob Mar 01 '18 at 17:56
  • @Mohsen is your question solved? – Tung Fam Mar 01 '18 at 22:02
  • This code works fine. The issues was in the simulator I used yesterday. Everything works as I wanted it to be when tested in an iPhone. I was not sure if I needed to use the delegate I still get confused about it. I do not need it in this case as you said [@Rob](https://stackoverflow.com/users/1271826/rob) – Mohsen Mar 02 '18 at 13:26

2 Answers2

3

I also had this issue, at least in a playgrounds prototype...

I put all of the translation (that you have in the changed state) inside of a UIViewProperty animator that I had defined within the handlePanGesture function and then called .startAnimation() within the began/changed state.

It takes a bit of tweaking on the animation but its a lot smoother for me..

Ben E.
  • 97
  • 1
  • 4
1

This code works fine. The issues was in the simulator I used yesterday. Everything works as I wanted it to be when tested in an iPhone.

Mohsen
  • 193
  • 1
  • 12