无限UIScrollView在iOS4.3而不是iOS5中获得奇怪的行为 [英] Infinite UIScrollView gets strange behavior in iOS4.3 not iOS5
问题描述
我实现了一个包含UIViews的无限UIScrollView。在iOS5(模拟器和iphone)中滚动时,它可以很好地工作。但是在iOS 4.3(SIM和手机)中它有点疯狂,滚动传递的视图比它应该多(比iOS5大10-15倍的视图)。并且为了让它更奇怪,如果我慢慢拖动它会按预期工作,所以它在我释放后不会继续滚动。
I've implemented an infinite UIScrollView that contains UIViews. When scrolling in iOS5 (simulator and iphone) it works beautifully. But in iOS 4.3 (sim and phone) it kinda goes a bit crazy and scrolls passed more views than it should (about 10-15x more views than in iOS5). And to make it more strange it works as expected if I drag slowly so it doesn't continue scroll after I release.
设置有点简单,我扩展了UIScrollView类。并添加宽度约为1500pt的UIView,在此添加我想要滚动的UIViews。滚动时,如果视图不在屏幕上,则会添加和删除视图。
The setup is kinda simple, I extend the UIScrollView class. And add UIView with a width of about 1500pt, in this I add my UIViews I want to scroll over. When scrolling the views are added and removed if they are off screen.
我认为我的问题在于此代码:
I think my problem lies with in this code:
- (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和iOS之间差异的模式祝你好运。
I've tried logging positions and offsets to try find a pattern with the difference between iOS4 & 5 with luck.
我从 http://developer.apple.com/videos/wwdc/2011/#advanced-scrollview-techniques (他们使用的是iOS5)。
I got the concept and some code from http://developer.apple.com/videos/wwdc/2011/#advanced-scrollview-techniques (they use iOS5).
编辑
照片(放在visiblePhotos数组中)是使用以下方法创建的:
Photos (that are put in the visiblePhotos array) are created with this methods:
- (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。
[self createItemContainer:[reportItems objectAtIndex:imageIndex]]
creates a UIVeiw that contains a photo`.
左右方法基本相同,并由下面的方法调用。 在每个帧上调用
tileImagesFromMinX
- (void)layoutSubviews
。
The left and right methods are basically the same and are invoked by the method below. And tileImagesFromMinX
is invoked on every frame by - (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];
}
}
推荐答案
我已经完成了一堆调查,并确定你不能只设置 self.contentOffset = ...;
并期望滚动视图在iOS 4.3中正确滚动/减速。因此,即使没有图像平铺(事实上,如果删除图像并在图像容器视图中放置背景,您会更清楚地注意到这一点),您实现的 recenterIfNecessary
不会在4.3下工作(这也会影响开发者网站上的示例代码!)。
I've done a bunch of investigating and determined that you can't just set self.contentOffset = ...;
and expect the scroll view to scroll/decelerate properly in iOS 4.3. So, even without the image tiling (and in fact you will notice this more clearly if you remove your images and just put a background on your image container view), your implementation of recenterIfNecessary
will not work under 4.3 (this also affects the sample code on the developer site!).
不幸的是,似乎解决这个问题的唯一方法是覆盖 -setContentOffset:
并在调用 super
之前修改那里的偏移量。请查看此问题,获取有关如何正常工作的一些指导。我希望你能用这个方法在iOS 5中运行...
Unfortunately, it seems the only way to work around this is to override -setContentOffset:
and modify the offset there before calling super
. Have a look at this question for some guidance on how to get that working correctly. I hope for your sake that this method will also work in iOS 5...
这篇关于无限UIScrollView在iOS4.3而不是iOS5中获得奇怪的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!