2012-06-10 45 views
25

我試圖在您實際滾動到下一頁時重新啓用分頁的scrollview的平滑動畫。它似乎是UIViewAnimationCurveEaseInOut,但我需要有一個「下一頁」按鈕並以編程方式觸發滾動。UIScrollview setContentOffset與非線性動畫?

這裏是我的代碼:

-(void) scrollToPage:(int)page 
{ 
    UIScrollView *scrollView = contentView; 
    CGPoint offset = CGPointMake(scrollView.bounds.size.width * page, scrollView.contentOffset.y); 
    [scrollView setContentOffset:offset animated: YES];  
    [self pageControlUpdate]; 
} 

-(void) scrollToNextPage 
{ 
    [self scrollToPage:(pageControl.currentPage + 1)]; 
} 

我不能設法再現UIViewAnimationCurveEaseInOut平滑, 要麼setContentOffset,或scrollRectToVisible ... 它進入下一個頁面與一個醜陋的線性動畫

我甚至嘗試手動設置動畫:

[UIView animateWithDuration:.5 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{ 
    scrollView.contentOffset = offset; 
} completion:^(BOOL finished) { } ]; 

我在哪裏錯了?

+0

我發現這個:http://developer.apple.com/library/ios/#DOCUMENTATION/WindowsViews/Conceptual/UIScrollView_pg/ScrollingViewContent/ScrollingViewContent.html確認我看到:'setContentOffset:animated:方法滾動內容到指定的內容偏移量。如果動畫參數爲YES,則滾動將以恆定速率從當前位置移動到指定位置。# – Diwann

+0

arg。沒有人可以有任何線索? – Diwann

+0

那麼,如果'UIViewAnimationCurveEaseInOut'不起作用,它可能是一個不同的動畫曲線。這是非常有可能蘋果使用這個動畫的自定義曲線。使用'CAPropertyAnimation',你可以用'CAMediaTimingFunction'的形式定義你自己的自定義曲線。這可能是值得玩弄不同的控制點。 –

回答

21

你讓你自己的動畫每次你必須通過NOanimated:參數:

- (void)scrollToPage:(int)page 
{ 
    UIScrollView *scrollView = contentView; 
    CGPoint offset = CGPointMake(scrollView.bounds.size.width * page, 
           scrollView.contentOffset.y); 

    [UIView animateWithDuration:.5 
          delay:0 
         options:UIViewAnimationCurveEaseInOut 
        animations:^{ 
         [scrollView setContentOffset:offset animated:NO]; 
        } completion:nil]; 

    [self pageControlUpdate]; 
} 
+0

和順便說一句。在某些情況下,修復動畫時間看起來很奇怪。例如你只需滾動2行,也需要半秒。而另一個方向,如果你有一個非常長的名單,而你從上到下滾動,它將在半秒內超快。 – 2012-06-14 11:23:12

+0

感謝您的解釋,但我只滾動整頁寬度,所以它總是看起來相同的速度。 我嘗試使用動畫:NO參數,但它保持固定速率滾動。我也嘗試改變UIViewAnimationCurve動畫,但它看起來是一樣的。 我正在嘗試Ole的自定義CAPropertyAnimation解決方案。 – Diwann

+0

這很好。小挑剔雖然,它應該是UIViewAnimationOptionCurveEaseInOut。 –

6

通過使用公共API的,我不相信這是目前可能的。假設您在動畫過程中不需要用戶交互,最好是動畫改變UIScrollView的子視圖(即滾動視圖的內容)的位置,然後在完成時不帶動畫地調整contentOffset。你可以做到這一點,像這樣:

- (void) scrollToPage:(int)page { 
    UIScrollView *scrollView = contentView; 
    scrollView.userInteractionEnabled = NO; 
    CGPoint offset = CGPointMake(scrollView.bounds.size.width * page, scrollView.contentOffset.y); 
    CGFloat delta = offset.x - scrollView.contentOffset.x; 

    __block int animationCount = 0; 
    for (UIView *view in scrollView.subviews) { 
     [UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 
      animationCount++; 
      CGRect frame = view.frame; 
      frame.origin.x -= delta; 
      view.frame = frame; 
     } completion:^(BOOL finished) { 
      animationCount--; 
      if (animationCount == 0) { 
       scrollView.contentOffset = offset; 
       for (UIView *view in scrollView.subviews) { 
        CGRect frame = view.frame; 
        frame.origin.x += delta; 
        view.frame = frame; 
       } 
       scrollView.userInteractionEnabled = YES; 
      } 
     }]; 
    } 
} 

我可以證實這一點按預期工作,我測試了它自己。

+0

是的,這是一個有趣的替代解決方案。但是我確實需要使用實時的contentOffset值來在滾動時將我的視圖移動到滾動視圖中,並且此解決方案不會觸發scrollviewdidscroll。 – Diwann

+0

當你在最後設置'contentOffset'時,它會觸發'scrollViewDidScroll'。但是您可以提取您在'scrollViewDidScroll'中執行的任何額外處理,並在此方法中使用它。 –

+0

或者,您可以將所有'UIScrollView'子視圖嵌入到另一個'UIView'中,您可以繼承和重寫'setFrame:',因爲在動畫過程中它基本上等同於'scrollViewDidScroll'。 –

4
[UIView animateWithDuration:(Animation_Duration) 
          delay:0.0 
         options:UIViewAnimationOptionCurveEaseInOut 
        animations:^{ 
        [scroll setContentOffset:CGPointMake(PointX, PointY) animated:NO]; 
         } 
        completion:^(BOOL finished){}];` 
3

該類絕對救了我的命:

MOScroll on GitHub.com

- (void)setContentOffset:(CGPoint)contentOffset withTimingFunction:(CAMediaTimingFunction *)timingFunction duration:(CFTimeInterval)duration;

就像私人API,但與所有公共方法和數學。

+0

MOScroll的工作鏈接:https://github.com/plancalculus/MOScrollView – Koen