Ross Barbish
Ross Barbish

Reputation: 679

Endless UICollectionView Slideshow + scrollToItemAtIndexPath

We have a UICollectionView that fills the entire screen to mimic a full-screen photo slideshow. The collection view's data is backed by a NSFetchedResultsController. Only one cell of the collection view displays on the screen at any given time. There is also a repeatable NSTimer set at an interval of 5 seconds that fires off a method "gotoNextPage" which calls scrollToItemAtIndexPath to the next fetched object (the next UICollectionView cell, the next slideshow photo). This is a smooth transition forward. When we get to the end of the slideshow we would like to seamlessly advance forward to the first photo and start the slideshow over again. Of course when we scrollToItemAtIndexPath back to the first photo it scrolls backwards rapidly (depending on how many fetched objects we have). We want the forward animation to be consistent no matter if you are at the beginning, middle, or end of the slideshow/UICollectionView.

Does anyone have a creative way to solve this problem?

Thanks

Upvotes: 0

Views: 1082

Answers (1)

pbasdf
pbasdf

Reputation: 21536

You could just let the index path item number increase continuously, and base your cellForItemAtIndexPath and other table logic on the remainder after dividing by the photo count. So you could code:

NSUInteger photoCount  = [[self.fetchedResultsController fetchedObjects] count];
NSIndexPath *fetchIndexPath = [NSIndexPath indexPathForItem:(indexPath.item % photoCount) inSection:0];
Photo *myPhoto = [self.fetchedResultsController objectAtIndexPath:fetchIndexPath];

A similar approach should work in the other tableView/NSFetchedResultsController datasource/delegate methods. EDIT As you note in your comment, you would have to set numberOfItemsInSection to a very large number (NSIntegerMax?).

Alternatively... You could amend your cellForItemAtIndexPath so that there is an extra cell, after the final photo, which contains the same photo as for row 0.

Photo *myPhoto
NSUInteger photoCount  = [[self.fetchedResultsController fetchedObjects] count];
if (indexPath.item = photoCount) {
    myPhoto = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
} else {
    myPhoto = [self.fetchedResultsController objectAtIndexPath:indexPath];
}
... configure cell...

You would have to amend numberOfItemsInSection to return photoCount+1.

After you scroll forward to this new final cell, scroll immediately to the first cell but without animation. Since the first and last cell have the same photo, the user will not see any transition. Then you can revert to scrolling forward with animation.

if (currentItem == photoCount -1) {
    [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:photoCount inSection:0] atScrollPosition:<your preference> animated:NO];
    [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:<your preference> animated:YES];
} else {
    [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:(currentItem+1) inSection:0] atScrollPosition:<your preference> animated:YES];
}

Upvotes: 1

Related Questions