iphone - 如何在 UIScrollView 中同时拖动和移动某些东西并滚动

标签 iphone ios uiscrollview aqgridview

我正在编写一个应用程序,它具有类似于 iBooks 的书架 View 。

现在的问题是:我可以将一本书从一个地方拖放到另一个地方。但是当我将书拖到 ScrollView 的底部时,如何让这些同时发生:

  1. 使 ScrollView 向下滚动
  2. 让书跟着我的手指走
  3. 将其他书籍放在正确的位置,并带有动画效果,例如在跳板上移动应用程序

我知道Github上有AQGridView,但是springboard demo好像不支持同时滚动和移动。(我已经设置scrollEnable为YES了)

最佳答案

我会给你我的解决方案,但由于整个事情相当大,我只会给你相关的片段。

此外,请注意,我使用手势识别器进行拖动 (UILongPressGestureRecognizer),因为这是用户在我的应用程序中启动拖动的方式,方法是将手指按住对象。因此,您可以拖动的每个 subview 都有自己的 UILongPressGestureRecognizer 分配给它,并且该识别器的目标/选择器位于另一个管理 ScrollView 和 subview 的类中。

这是手势识别器的目标:

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

与你相关的事情:

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

这是代码

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

这个东西只做水平滚动,但处理垂直会非常相似。它的作用是:

  • 检查您是否拖入了 ScrollView 的边界区域(我使用左右 30% 的边界作为应该发生滚动的区域)。但前提是用户朝那个方向移动(xDelta < 0 表示左侧,xDelta > 0 表示右侧)
  • 接下来,我使用速度常数计算 ScrollView 的移动量,并根据用户与 ScrollView 实际边界的距离进行缩放,因此速度与用户与边缘的距离成正比。
  • 最后一步是使用非动画 scrollRectToVisible 滚动 ScrollView 。当然 您拖动的 View 会随之移动,因此我们会通过其中心的相反偏移量对其进行补偿。

希望对您有所帮助。

关于iphone - 如何在 UIScrollView 中同时拖动和移动某些东西并滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6805825/

相关文章:

ios - 从 Objective-C 对象生成 MD5 哈希

ios - 如何让图像在 iOS 的分页 ScrollView 中缩放?

ios4 - 创建垂直 UIPageControl

iphone - 调用pushViewController时EXC_BAD_ACCESS

ios - 以编程方式创建的后退按钮未显示在导航栏中?

iphone - 将 iPad 应用程序中的文本数据保存为可以从 "notes app"打开的注释?

ios - 关闭 UIScrollView 的滚动但保留缩放功能

iphone - 是否可以更改包标识符?

IOS UITableview 如何在表格动画完成后采取行动

iphone - iPhone:如何将“yyyyMMddThhmmss”格式字符串转换为NSDate?