1
votes

I have a UIView that can be dragged with the finger which I've implemented by using a UIPanGestureRecognizer. This allows me to drag a view horizontally ; left or right.

I make my view moving while receiving the following state from the UIPanGestureRecognizer (using the translationInView: method):

  • UIGestureRecognizerStateBegan
  • UIGestureRecognizerStateChanged

What happens for now, is the view stops moving as soon as the finger leaves the surface of the screen, which renders a non natural effect.

What I would like, would be that the dragging view decelerates starting from the state UIGestureRecognizerStateEnded by stopping smoothly.

Such a behavior is used by UIScrollView class and subclasses (UIWebView, UITableView, etc.).

I've tried severals approaches by calculating from the velocity, the time the touch occurred and stopped a stop distance, etc. But honestly I have a feeling of going nowhere to get a natural behavior. I even tried to use physics engine like Chipmunk. But I find this to complicated for what I try to achieve, and I'm pretty sure there should be a better (if not easier) solution.

Thanks a lot!

Jérémy

1
Have you experimented with UIScrollView decelarationRate? - westsider
I'm not using a UIScrollView at all, nor a subclass. I just want to implement a mechanism of deceleration. - jchatard
For now, still have no perfect solution... If you have ideas, you're welcome! But frankly I think the best approach is to use a physics engine which handle all this seamlessly. - jchatard

1 Answers

1
votes

In your gesture recognizer, make it so that when your finger leaves the screen, you begin an animation to continue to scroll a bit, for a short duration, with an "Ease Out" transition.

Maybe something like:

[UIView beginAnimations:@"FingerOff" context:nil];
[UIView setAnimationDuration:0.25f];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationCurve:UIAnimationViewEaseOut];
[myView setFrame:newFrame];
[UIView commitAnimation];

You can substitute setFrame to something else - whatever establishes how you want to scroll or view - maybe even a setCenter. Make it a scroll a bit "further" than the current position.