2011-07-24 173 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

相關問題