使用 UIPanGestureRecognizer 时设置可拖动 UIView 的位置限制

发布于 2025-01-06 05:12:47 字数 2239 浏览 0 评论 0原文

这个问题与我最近发表的这篇文章有一些关系: 拖动一个 UIView 一半,然后它自己移动

简而言之,我有一个可拖动的 UI 视图在窗口底部部分可见。有一个“拉动选项卡”,用户可以使用它在屏幕上向上或向下拖动视图。我使用此代码对上下位置的 Y 位置进行了限制,但我不知道这是否是正确的方法:

- (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]];
            }
        }
    }

}

我认为这看起来很难看,但如果用户拖动视图,它会起作用慢慢地。问题是,如果用户在屏幕上非常快速地向上或向下拖动视图,则视图可能会被拉到超出我对 Y 位置设置的限制。例如,在底部可拖动视图的默认状态下,我能够以快速的速度将视图一直拖动到导航栏上方!

是否有正确的方法来设置视图可以拖动多远的限制,并在此gestureRecognizer回调中正确处理?

作为参考,以下是测试应用程序的图片:

默认屏幕,可拖动视图底部和拉片

视图被拖动到正确的最大 Y 位置

谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

过期情话 2025-01-13 05:12:47

问题在于,在以下代码中:

if(blogTextView.frame.origin.y >= maxYPos)
{
    [piece setCenter:CGPointMake([piece center].x, [piece center].y + translation.y)];
    [gestureRecognizer setTranslation:CGPointZero inView:[piece superview]];
}

而这一个:

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]];
}

您应该使用 blogTextView.frame.origin.y 的未来值(如果执行 if 内的代码,您将获得的值)集团。)

换句话说,你总是在做额外的翻译。当缓慢拖动时你不会注意到这一点,因为额外的平移并不重要,但当快速拖动时它就变得很重要,你会注意到错误的结果。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文