Search code examples
swifttranslationswipevelocityuipangesturerecognizer

Get Movement Translation Difference on swiping left a frame beyond a fixed point then changing direction by swiping right to update the frame


The scenario is as the following: User taps and holds down finger to swipe a UIView to left to reveal another view beneath. The visible view is scrollable 50 points to left and then it stops. View's frame translates with -50

In all this time the user is holding tap continuously and finally changes direction to right and can scroll until view reaches initial position where its frame translation was 0.

The problem is that while user scroll beyond the fixed point of -50 where the frame stops, translation is still recored and when the user changed swiping direction to the right the View moves with a difference which I would like to eliminate. That Difference in Translation seem to be form the view's stopping point to the point there user changed swiping direction. Here's my code:

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        drabbleLayer.isUserInteractionEnabled = true
        let recognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan(recognizer:)))
       drabbleLayer.addGestureRecognizer(recognizer)
    }

    @objc func handlePan(recognizer: UIPanGestureRecognizer) {
        if recognizer.state == .began {
            originalCenter = self.drabbleLayer!.center
        }

        var velocity = recognizer.velocity(in: drabbleLayer)

        if recognizer.state == .changed {

            let targetX: CGFloat = -50.0

            var tranlastion = recognizer.translation(in: self.drabbleLayer!)

            var newX: CGFloat {
                return originalCenter.x + tranlastion.x
            }

            if velocity.x < 0 {

                let log = tranlastion.x >= targetX
                let log2 = drabbleLayer.frame.origin.x >= targetX

                if  log && log2 {

                    dabbleLayer!.center.x = newX

                } else { drabbleLayer.center.x = -targetX * 2}

            } else {
                //this is where the Difference in Translation is noticeable if user swipes way beyond the stopping point to the left 
                if drabbleLayer.frame.origin.x <= 0 {
                    drabbleLayer!.center.x = newX

                } else {
                    //here view has to get to a full stop. Doesn't seem to work properly. 
                    drabbleLayer.frame.orgin.x = 0}
            }
        }
}

In my full code I printed the translation values so I can see where it changes. I am checking swiping direction on velocity. The thing is that after changing direction translation varies form let's say a value of -74 to 200. In this case the difference would be 74(translation) - 50(which is the stopping point, targetX in my code. Also, this difference seems to also appear if the user swipes from right to left.

Can I capture the difference in translation and get rid of it somehow immediately before changing direction ?


Solution

  • Finally I found myself a solution for this problem. I was still unable to find a direct solution like saving the latest value of translation just before changing direction so I could compute the difference in translation.

    However, alternatively and immediately before changing direction I did set translation to the targetX value, so there was no need to subtract any difference in translation anymore. Here's my new code:

    @objc func handlePan(recognizer: UIPanGestureRecognizer) {
    
        var tranlastion = recognizer.translation(in: self.incomeDrabbleLayer!)
    
        var newX: CGFloat {
            return originalCenter.x + tranlastion.x
        }
    
        let targetX: CGFloat = -50.0
    
        if recognizer.state == .began {
            originalCenter = self.incomeDrabbleLayer!.center
        }
    
        let velocity = recognizer.velocity(in: incomeDrabbleLayer)
    
        if recognizer.state == .changed {
    
            if velocity.x < 0 {
                if incomeDrabbleLayer.frame.origin.x > targetX {
    
                    incomeDrabbleLayer.center.x = newX
    
                } else {
    
                    incomeDrabbleLayer.frame.origin.x = targetX
    
                    let targetTranslationPoint = CGPoint(x: targetX, y: 0)
                    recognizer.setTranslation(targetTranslationPoint, in: incomeDrabbleLayer)
                }
    
            } else {
    
                if incomeDrabbleLayer.frame.origin.x < 0 {
                    incomeDrabbleLayer.center.x = newX
                } else {
                    incomeDrabbleLayer.frame.origin.x = 0
                    recognizer.setTranslation(.zero, in: incomeDrabbleLayer)
                }
    
            }
        }
    
    }