2011-08-17 16 views
4

我實現了一個包含UIViews的無限UIScrollView。當在iOS5(模擬器和iPhone)中滾動時,它的效果非常好。但在iOS 4.3(模擬和手機)中,它有點瘋狂,滾動通過的視圖比它應該多(大約比iOS5多10-15倍)。爲了讓它更奇怪,它可以像預期的那樣工作,如果我拖慢拖,所以它在發佈後不會繼續滾動。無限UIScrollView在iOS4.3中得到奇怪的行爲而不是iOS5

設置很簡單,我擴展了UIScrollView類。並添加寬度約爲1500pt的UIView,在此我添加我想要滾動的UIViews。滾動視圖時,如果它們不在屏幕上,則視圖被添加並移除。

我想我的問題出在此代碼:

- (void)recenterIfNecessary { 
    CGPoint currentOffset = [self contentOffset]; 
    CGFloat contentWidth = [self contentSize].width; 
    CGFloat centerOffsetX = (contentWidth - [self bounds].size.width)/2.0; 
    CGFloat distanceFromCenter = fabs(currentOffset.x - centerOffsetX); 
    UIView *image; 

    if (distanceFromCenter > (contentWidth/4.0)) { 
     // Recenter the ScrollView so we never reach the edge 
     self.contentOffset = CGPointMake(centerOffsetX, currentOffset.y); 
     // Move visiblePhotos to new position to adjust to new contentOffset 
     for (image in visiblePhotos) { 
      CGPoint center = image.center; 
      center.x += (centerOffsetX - currentOffset.x); 
      image.center = center; 
     } 
    } 
} 

recenterIfNecessary這裏調用:

- (void)layoutSubviews { 
    [super layoutSubviews];  
    [self recenterIfNecessary]; 
    [self tileImagesFromMinX:minVisibleX toMaxX:maxVisibleX]; 
    //.... 
} 

我試過記錄位置和偏移,試圖找到之間的差異中的模式運氣好的iOS4 & 5。

我從http://developer.apple.com/videos/wwdc/2011/#advanced-scrollview-techniques(他們使用iOS5)得到的概念和代碼。

編輯

照片(被放在visiblePhotos陣列中)都使用此方法創建:

- (CGFloat)placeNewImageOnRight:(CGFloat)rightEdge { 
    imageIndex = imageIndex < 0 ? ([reportItems count] - 1) : (imageIndex >= [reportItems count] ? 0 : imageIndex); 

    UIView *image = [self createItemContainer:[reportItems objectAtIndex:imageIndex]]; 
    [visiblePhotos addObject:image]; 

    CGRect frame = [image frame]; 
    frame.origin.x = rightEdge; 
    frame.origin.y = [imageContainerView bounds].size.height - frame.size.height; 

    [image setFrame:frame]; 

    imageIndex += 1; 

    return CGRectGetMaxX(frame); 
} 

- (CGFloat)placeNewImageOnLeft:(CGFloat)leftEdge { 
    imageIndex = imageIndex < 0 ? ([reportItems count] - 1) : (imageIndex >= [reportItems count] ? 0 : imageIndex); 

    UIView *image = [self createItemContainer:[reportItems objectAtIndex:imageIndex]]; 
    [visiblePhotos insertObject:image atIndex:0]; 

    CGRect frame = [image frame]; 
    frame.origin.x = leftEdge - frame.size.width; 
    frame.origin.y = [imageContainerView bounds].size.height - frame.size.height; 
    [image setFrame:frame]; 

    imageIndex -= 1; 

    return CGRectGetMinX(frame); 
} 

[self createItemContainer:[reportItems objectAtIndex:imageIndex]]創建一個包含photo`一個UIVeiw。

左側和右側方法基本相同,並由以下方法調用。並且tileImagesFromMinX在每個幀上由- (void)layoutSubviews調用。

- (void)tileImagesFromMinX:(CGFloat)minVisibleX toMaxX:(CGFloat)maxVisibleX { 
    if ([visiblePhotos count] == 0) { 
     [self placeNewImageOnRight:minVisibleX]; 
    } 

    UIView *lastImage = [visiblePhotos lastObject]; 
    CGFloat rightEdge = CGRectGetMaxX([lastImage frame]); 
    while (rightEdge < maxVisibleX) { 
     rightEdge = [self placeNewImageOnRight:rightEdge]; 
    } 

    UIView *firstImage = [visiblePhotos objectAtIndex:0]; 
    CGFloat leftEdge = CGRectGetMinX([firstImage frame]); 
    while (leftEdge > minVisibleX) { 
     leftEdge = [self placeNewImageOnLeft:leftEdge]; 
    } 

    lastImage = [visiblePhotos lastObject]; 
    while ([lastImage frame].origin.x > maxVisibleX) { 
     [lastImage removeFromSuperview]; 
     [visiblePhotos removeLastObject]; 
     lastImage = [visiblePhotos lastObject]; 
    }  

    firstImage = [visiblePhotos objectAtIndex:0]; 
    while (CGRectGetMaxX([firstImage frame]) < minVisibleX) { 
     [firstImage removeFromSuperview]; 
     [visiblePhotos removeObjectAtIndex:0]; 
     firstImage = [visiblePhotos objectAtIndex:0]; 
    } 
} 
+0

你想讓'visiblePhotos'滾動邊緣或環繞或什麼? 'visiblePhotos'數組在哪裏創建? – jtbandes

+0

我更新了問題。我的目標是擁有和無盡的滾動。所以用戶可以將雙向滾動到無限遠,永遠不會到達最終。所有照片都按照正確的順序重新排列。 – fredrik

+0

照片是否循環?我不知道'visiblePhotos'來自哪裏。 – jtbandes

回答

6

我已經做了一堆調查和確定,你不能只是設置self.contentOffset = ...;並期望滾動視圖滾動/ iOS中4.3適當減速。因此,即使沒有圖像平鋪(事實上,如果您刪除圖像並將圖像背景放在圖像容器視圖上,您​​會更清楚地注意到這一點),但您的實施recenterIfNecessary在4.3下不起作用(這也會影響示例代碼在開發者網站!)。

不幸的是,似乎解決此問題的唯一方法是在調用super之前覆蓋-setContentOffset:並修改偏移量。查看this question,瞭解如何正確工作的一些指導。我希望你的緣故,這種方法也可以在iOS 5中工作...

+0

我刪除了'recenterIfNecessary'的調用並覆蓋了'setContentOffset',並且只處理contentOffset。現在它有點不錯。有時它會跳躍一下。但它確實有所改善。我會盡量多玩一點數學。 – fredrik

+0

@fredrik什麼運氣? – jtbandes

+0

仍然無法工作,仍然跳來跳去。 – fredrik