首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在UIScrollView中同时拖动、移动和滚动

如何在UIScrollView中同时拖动、移动和滚动
EN

Stack Overflow用户
提问于 2011-07-24 08:45:39
回答 1查看 6.5K关注 0票数 11

我正在写一个像iBooks这样的书架视图的应用程序。

现在的问题是:当我将图书拖到滚动视图的底部时,我可以将一本书从一个地方拖到another.But,如何使这些情况同时发生:

  1. 使滚动视图向下滚动
  2. 保持该书跟随“我的手指”
  3. 将其他的书放在正确的位置,动画就像在跳板上移动应用程序

我知道在Github中有一个AQGridView,但是看起来跳板演示不支持滚动和移动(我已经将scrollEnable设置为YES)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-07-24 09:13:08

我将给出我的解决方案,但是由于整个事情都很大,所以我将只给您提供相关的片段。

此外,请注意,我使用了一个手势识别器的拖拽(UILongPressGestureRecognizer),因为这是如何启动在我的应用程序中,他的手指按在对象上。因此,每个可以拖动的子视图都有自己的UILongPressGestureRecognizer分配给它,而该识别器的目标/选择器位于管理滚动视图和子视图的另一个类中。

以下是手势识别器的目标:

代码语言:javascript
复制
-(void)dragged:(UILongPressGestureRecognizer *)panRecog
{
    if (panRecog.state == UIGestureRecognizerStateBegan)
    {
        UIView * pannedView = panRecog.view;

        dragView = pannedView;
        dragView.center = [panRecog locationInView:scrollView];

        [scrollView bringSubviewToFront:dragView];

        [self startDrag]; // Not important, changes some stuff on screen to show the user he is dragging 
        return;
    }

    if (panRecog.state == UIGestureRecognizerStateChanged)
    {
        int xDelta  = dragView.center.x - [panRecog locationInView:scrollView].x;
        dragView.center = [panRecog locationInView:scrollView];

        [self scrollIfNeeded:[panRecog locationInView:scrollView.superview] withDelta:xDelta];

        return;
    }

    if (panRecog.state == UIGestureRecognizerStateEnded)
    {
        [self endDrag]; // Not important, changes some stuff on screen to show the user he is not dragging anymore
    }
}

与你相关的事情:

启动拖动时,

  • 将存储在dragView中的哪个视图,并将其中心设置为手指相对于它所在的滚动视图的位置。
  • startDrag对您来说并不重要,它会更改屏幕上的一些内容,以显示当我们实际移动对象( UIGestureRecognizerStateChanged )时,用户正在拖动
  • --我得到了用户移动手指的点数,并使用这个增量以及用户的手指位置来检查是否需要在scrollIfNeeded中移动滚动视图。

这是密码

代码语言:javascript
复制
-(void)scrollIfNeeded:(CGPoint)locationInScrollSuperview withDelta:(int)xDelta
{
    UIView * scrollSuperview = scrollView.superview;
    CGRect bounds = scrollSuperview.bounds;
    CGPoint scrollOffset = scrollView.contentOffset;
    int xOfs = 0;
    int speed = 10;

    if ((locationInScrollSuperview.x > bounds.size.width * 0.7) && (xDelta < 0))
    {
        xOfs = speed * locationInScrollSuperview.x/bounds.size.width;
    }

    if ((locationInScrollSuperview.x < bounds.size.width * 0.3) && (xDelta > 0))
    {
        xOfs = -speed * (1.0f - locationInScrollSuperview.x/bounds.size.width);
    }

    if (xOfs < 0)
    {
        if (scrollOffset.x == 0)    return;
        if (xOfs < -scrollOffset.x) xOfs = -scrollOffset.x;
    }
    scrollOffset.x += xOfs;
    CGRect rect = CGRectMake(scrollOffset.x, 0, scrollView.bounds.size.width, scrollView.bounds.size.height);
    [scrollView scrollRectToVisible:rect animated:NO];
    CGPoint center = dragView.center;
    center.x += xOfs;
    dragView.center=center;
}

这件事只做水平滚动,但处理垂直将是相当相似的。它所做的是:

  • 检查是否拖动到滚动视图的边界区域(我使用30%的左右边框作为滚动发生的区域)。但是,只有当用户向该方向移动(左xDelta <0,右xDelta >0)时,
  • 下一步才计算移动滚动视图的数量,使用速度常量,并根据用户离滚动视图实际边框的距离进行缩放,这样速度与用户距离边缘的距离成正比。
  • 最后一步是使用非动画scrollRectToVisible滚动滚动视图。当然,您的拖放视图向前移动,因此我们用与其中心相反的偏移量对其进行补偿。

希望这能帮到你。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6805825

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档