2011-07-24 128 views
8

我在写一个应用程序,它具有像iBooks一样的书架视图。如何拖动和移动东西,并在UIScrollView同时滚动

现在的问题是:我可以拖动并从地点放置一本书another.But如何使这些发生在同一时间,当我拖到书滚动视图的底部:

  1. 使滚动视图向下滚动
  2. 把这本书按照我的手指
  3. 地方在正确的地方的其他书籍动画像跳板

移动应用程序,我知道有一个AQGridView在Github,但似乎跳板演示不支持滚动和同时移动(我已经将scrollEnable设置为YES)

回答

13

我会给你我的解决方案,但由于整个事情是相当大的我我会给你相关的片段。另外,请注意,我使用手势识别器进行拖动(UILongPressGestureRecognizer),因为这是用户在我的应用程序中启动拖动的方式,方法是将他的手指按在对象上。因此,每个可以拖动的子视图都有自己的UILongPressGestureRecognizer分配给它,并且该识别器的目标/选择器位于另一个同时管理scrollview和子视图的类中。

这里是手势识别的目标:

  • 当开始我店拖动它查看我拖动dragView并设置其中心:

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

    ,对于你相关的事情成为你的手指相对于它所处的滚动视图的位置。

  • startDrag对你不重要,它改变屏幕上的某些东西以显示他正在拖动的用户
  • 当我们实际移动我们的对象(UIGestureRecognizerStateChanged)时,我得到了用户移动他的手指的点数,并将该增量与用户的手指位置一起用于检查scrollId是否需要在scrollIfNeeded中移动。

这是代码

-(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滚动scrollview。当然 您拖动的视图会沿着它移动,所以我们用其中心的相反偏移来补偿。

希望这可以帮助你。

+0

这就是我需要的!真的非常感谢 – ultragtx

+0

干得好,谢谢;)! – Oliver

+0

这工程太棒了!但是,您的xDelta计算应该是当前位置减去最后一个位置。最终值减去初始值,这样一个正xDelta减号用户向右拖,而负xDelta意味着他们拖到左侧。但它也适用于你的方式。 :) – ucangetit

相关问题