【问题标题】:Infinite UIScrollView gets strange behavior in iOS4.3 not iOS5无限 UIScrollView 在 iOS4.3 而不是 iOS5 中得到奇怪的行为
【发布时间】:2011-10-28 18:39:11
【问题描述】:

我已经实现了一个包含 UIView 的无限 UIScrollView。在 iOS5(模拟器和 iphone)中滚动时效果很好。但在 iOS 4.3(sim 和手机)中,它有点疯狂,滚动通过的浏览量比它应该的要多(大约比 iOS5 多 10-15 倍)。为了让它更奇怪,如果我慢慢拖动它会按预期工作,所以在我释放后它不会继续滚动。

设置有点简单,我扩展了 UIScrollView 类。并添加宽度约为 1500pt 的 UIView,在此我添加我想要滚动的 UIView。滚动视图时,如果它们不在屏幕上,则会添加和删除它们。

我认为我的问题在于这段代码:

 - (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]] 创建一个包含照片的 UIVeiw。

left 和 right 方法基本相同,由下面的方法调用。 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];
    }
}

【问题讨论】:

  • 你想让你的visiblePhotos 滚动到边缘还是环绕或者什么? visiblePhotos 数组是在哪里创建的?
  • 我更新了问题。我的目标是拥有无尽的滚动。因此,用户可以双向滚动到无穷大,永远不会到达终点。所有照片都按正确的顺序重新排列。
  • 照片是否循环播放?我不知道visiblePhotos来自哪里。
  • 照片循环播放。 visiblePhotos 是在我的 ScrollView 子类的 init 方法中声明的 NSMutableArray。照片仅从placeNewImageOnLeftplaceNewImageOnRight(void)tileImagesFromMinX:(CGFloat)minVisibleX toMaxX:(CGFloat)maxVisibleX 中添加/删除
  • 抱歉,没有注意到编辑。我再看看。

标签: iphone objective-c uiscrollview


【解决方案1】:

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

不幸的是,解决此问题的唯一方法似乎是覆盖-setContentOffset: 并在调用super 之前修改那里的偏移量。查看this question 以获得有关如何使其正常工作的一些指导。我希望为您着想,此方法也适用于 iOS 5...

【讨论】:

  • 我删除了对 recenterIfNecessary 的调用并覆盖了 setContentOffset 并且只处理其中的 contentOffset。现在它有点工作。有时它会跳来跳去。但它确实有所改善。我会尝试更多地使用数学。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-03
  • 2012-01-14
  • 1970-01-01
相关资源
最近更新 更多