Reputation: 3159
This question has some relation to this post I made recently: Drag a UIView part-way, then it moves on its own
In short, I have a draggable UI view partly visible at the bottom of the window. There is a "pull tab" that the user can use to drag the view upwards or downwards on the screen. I have placed limits on the Y position for the upper and lower positions using this code, but I have no clue if this is the right way to do it:
- (void)panPiece:(UIPanGestureRecognizer *)gestureRecognizer
{
UIView *piece = [gestureRecognizer view];
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged)
{
CGPoint velocity = [gestureRecognizer velocityInView:[piece superview]];
CGPoint translation = [gestureRecognizer translationInView:[piece superview]];
if(velocity.y < 0) //user is dragging the view upwards the screen
{
// Set the maximum Ypos as the top 1/3rd of the screen
CGFloat maxYPos = self.view.frame.size.height/3;
if(blogTextView.frame.origin.y >= maxYPos)
{
[piece setCenter:CGPointMake([piece center].x, [piece center].y + translation.y)];
[gestureRecognizer setTranslation:CGPointZero inView:[piece superview]];
}
}
else
{
// User is dragging the view downwards the screen
// Set the lowest Y position to be 420
if(blogTextView.frame.origin.y <= 420) //size of remaining view
{
[piece setCenter:CGPointMake([piece center].x, [piece center].y + translation.y)];
[gestureRecognizer setTranslation:CGPointZero inView:[piece superview]];
}
}
}
}
I think this looks ugly, but it works if the user is dragging the view slowly. The problem is if the user drags the view very rapidly upward or downward the screen, then the view can be pulled beyond the limits I put on the Y position. For example, in the default state with the draggable view on the bottom, I was able to drag the view in a snap-like speed all the way to over the navigation bar!
Is there a correct way to set the limits of how far a view can be dragged and will be dealt with correctly in this gestureRecognizer callback?
For reference, here are pics of the test app:
Default screen with draggable view at the bottom and the pull tab
View dragged up to its correct max Y position
Thank you!
Upvotes: 1
Views: 1806
Reputation: 27506
The problem is that in the following code:
if(blogTextView.frame.origin.y >= maxYPos)
{
[piece setCenter:CGPointMake([piece center].x, [piece center].y + translation.y)];
[gestureRecognizer setTranslation:CGPointZero inView:[piece superview]];
}
And this one:
if(blogTextView.frame.origin.y <= 420) //size of remaining view
{
[piece setCenter:CGPointMake([piece center].x, [piece center].y + translation.y)];
[gestureRecognizer setTranslation:CGPointZero inView:[piece superview]];
}
You you should use the future value of blogTextView.frame.origin.y
(the value that you would obtain if you executed the code inside the if bloc.)
In other words, you are always doing an extra translation. And you can't notice that when dragging slowly because the extra translation is not important, but it becomes important when dragging quickly and you can notice the wrong result.
Upvotes: 3