So I'm modifying the PhotoScroller sample from Apple, and I'm trying to add an infinite looping feature, i.e: when the user scrolls to the last picture, the first one shows up next.
To do so, I multiplied the contentSize width by a hundred (to fake the infinite loop), multiplied the last needed page index by a hundred as well, and use a fake index (index modulo self.imageCount) to display the correct image, as follow:
- (CGSize)contentSizeForPagingScrollView {
// We have to use the paging scroll view's bounds to calculate the contentSize, for the same reason outlined above.
CGRect bounds = pagingScrollView.bounds;
double rightBounds = bounds.size.height;
// return CGSizeMake(bounds.size.width * [self imageCount], rightBounds); // no infinite loop
return CGSizeMake(bounds.size.width * [self imageCount] * 100, rightBounds); // with infinite loop
}
- (void)tilePages
{
// Calculate which pages are visible
CGRect visibleBounds = pagingScrollView.bounds;
int firstNeededPageIndex = floorf(CGRectGetMinX(visibleBounds) / CGRectGetWidth(visibleBounds));
int lastNeededPageIndex = floorf((CGRectGetMaxX(visibleBounds)-1) / CGRectGetWidth(visibleBounds));
firstNeededPageIndex = MAX(firstNeededPageIndex, 0);
// lastNeededPageIndex = MIN(lastNeededPageIndex, [self imageCount] - 1); // no infinite loop
lastNeededPageIndex = MIN(lastNeededPageIndex, [self imageCount] * 100 - 1); // with infinite loop
// Recycle no-longer-visible pages
for (ImageScrollView *page in visiblePages) {
if (page.index < firstNeededPageIndex || page.index > lastNeededPageIndex) {
[recycledPages addObject:page];
[page removeFromSuperview];
}
}
[visiblePages minusSet:recycledPages];
int fakeIndex = firstNeededPageIndex;
// add missing pages
for (int index = firstNeededPageIndex; index <= lastNeededPageIndex; index++) {
fakeIndex = index % self.imageCount;
if (![self isDisplayingPageForIndex:fakeIndex]) {
ImageScrollView *page = [self dequeueRecycledPage];
if (page == nil) {
page = [[ImageScrollView alloc] init];
}
[self configurePage:page forIndex:fakeIndex];
[pagingScrollView addSubview:page];
[visiblePages addObject:page];
}
}
}
So as long as index == fakeIndex, the pictures display properly, but once the loop goes past that point, e.g: index = 5, fakeIndex =1, the page stays black and the image isn't displayed anymore.
However, I can see using the console that when [self configurePage:page forIndex:fakeIndex] is called, the right image name is fetched.
If anybody could take a little time to investigate the original sample code (http://developer.apple.com/library/ios/#samplecode/PhotoScroller/Introduction/Intro.html), and figure out what's wrong, it would be great.
Thank you.
The issue was in:
- (CGRect)frameForPageAtIndex:(NSUInteger)index {
// We have to use our paging scroll view's bounds, not frame, to calculate the page placement. When the device is in
// landscape orientation, the frame will still be in portrait because the pagingScrollView is the root view controller's
// view, so its frame is in window coordinate space, which is never rotated. Its bounds, however, will be in landscape
// because it has a rotation transform applied.
CGRect bounds = pagingScrollView.bounds;
CGRect pageFrame = bounds;
pageFrame.size.width -= (2 * PADDING);
pageFrame.origin.x = (bounds.size.width * index) + PADDING;
// pageFrame.origin.y -= 44;
return pageFrame;
}
The frame was taking the fakeIndex as multiplier for the horizontal origin, so the new page frame was placed on top of the first one. By passing both fakeIndex and index to [self configurePage:page forIndex:fakeIndex], I could pass the index as multiplier for the horizontal origin, and the new page frame would then be correct.