无限的UIScrollView在iOS4.3而不是iOS5中会出现奇怪的行为

fre*_*rik 4 iphone objective-c uiscrollview

我已经实现了一个包含UIViews的无限UIScrollView.在iOS5(模拟器和iphone)中滚动时,它可以很好地工作.但是在iOS 4.3(SIM和手机)中它有点疯狂,滚动传递的视图比它应该多(比iOS5大10-15倍的视图).并且为了让它更奇怪,如果我慢慢拖动它会按预期工作,所以它在我释放后不会继续滚动.

设置有点简单,我扩展了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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

recenterIfNecessary 在这里调用:

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

我已经尝试记录位置和偏移量,试着找到一个与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);
}
Run Code Online (Sandbox Code Playgroud)

[self createItemContainer:[reportItems objectAtIndex:imageIndex]] 创建一个包含照片的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];
    }
}
Run Code Online (Sandbox Code Playgroud)

jtb*_*des 6

我做了很多调查,并确定你不能只设置self.contentOffset = ...;并期望滚动视图在iOS 4.3中正确滚动/减速.因此,即使没有图像平铺(事实上,如果删除图像并在图像容器视图中放置背景,您会更清楚地注意到这一点),您的实现recenterIfNecessary将无法在4.3下工作(这也会影响示例代码开发者网站!).

不幸的是,似乎解决这个问题的唯一方法是-setContentOffset:在调用之前覆盖和修改那里的偏移量super.请查看此问题,以获得有关如何正常工作的一些指导.我希望你能用这个方法在iOS 5中运行...