I'm moving UIView
object using UIPanGestureRecognizer
— how much I drag my finger on screen, that much I move the view in the same direction (only in X - left or right, Y is not changing). It works fine, but with (very noticeable) delay.
Here is the method that handles the UIPanGestureRecognizer
event:
-(void)movePages:(UIPanGestureRecognizer *)sender
{
if (switchingMode == 1) {
if ([sender state] == UIGestureRecognizerStateBegan) {
fingerStartPosition = [sender locationInView:self.view].x;
viewStartPosition = [[viewControllers objectAtIndex:activeViewControllerIndex] view].center;
}
[[[[viewControllers objectAtIndex:activeViewControllerIndex] view] layer] setPosition:CGPointMake(viewStartPosition.x - (fingerStartPosition - [sender locationInView:self.view].x) , viewStartPosition.y)];
}
}
I've tried to set position of the view using its layer, I've also tried setting the frame, using animations with different durations, but everything behaved the same. Any idea why this delay occurs ?
Use a UILongPressGestureRecognizer
and set the minimumPressDuration
to 0.0
. This recognizes instantly and you get all the same updates including the UIGestureRecognizerStateChanged
with the updated location.
I found that it was faster responding if you use just regular touchesBegan, Moved and Ended. I even subclassed a UIGestureRecognizer, and it still had lag on the panning gesture. Even though the touchesBegan within the UIGestureRecognizer would trigger on time, the state change would take a half second to change its state... It seems faster to just use a plain old TouchesBegan, especially if you're cpu is doing a lot.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
if touches.count == 1
{
initialTouchLocation = (touches.first?.locationInView(self).x)!
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?)
{
if touches.count == 1
{
let locationInView = touches.first?.locationInView(self)
if !thresholdHit
{
//this is the threshold for x movement in order to trigger the panning...
if abs(initialTouchLocation - locationInView!.x) > 1
{
thresholdHit = true
}
}
else
{
if (self.frame.width != CGFloat(screenSize))
{
let panDelta = initialTouchLocation - locationInView!.x
}
}
}
}
The GestureRecognizer can't be sure, if it is a pan gesture, before you moved your finger some pixels. I don't know the exact tolerance value, but that is why you feel a delay.
Documentation:
A panning gesture is continuous. It begins when the minimum number of fingers allowed have moved enough to be considered a pan.
If you want instant movement, you probably need to build your own logic using touchesMoved:
.
Another approach could be, to animate to the first recognized point. But that doesn't remove the delay. For that approach you could have a look at my JDDroppableView on github.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With