I'm currently trying to implement a selection of photos in the same way as the Photos application, but with a custom image source. For the "photo scrolling" part, I used the Apple PhotoScroller sample code and adapted it. One of the main differences is that it is now integrated into the navigation controller (which is the photoPickerโs own navigation controller, and not one of the applications), with a navigation bar. I have a status and the navigation bar is translucent, and I set wantFullScreenLayout = YES on the entire view controller used in photoPicker. It seems to be working almost fine. The browse (the one that displays the thumbnails of all the photos on the album) is really full-screen, and I have to manually shift it so that the thumbnails first appear below the navigation bar. However, there is a glitch for the scroll part. For those who do not know the photoScroller code sample, it works with a custom UIViewController (PhotoViewController) with the UIScrollView attribute (pagingScrollView) and a custom UIScrollView (ImageScrollView) set with the UIView and NSInteger index attributes. Then, ImageScrollView instances are added / removed as PhotoScroller subviews.
Below is some code:
PhotoViewController.h
@interface PhotoViewController : UIViewController <UIScrollViewDelegate> { UIScrollView *pagingScrollView; NSMutableSet *recycledPages; NSMutableSet *visiblePages; IBOutlet UIToolbar *toolbar; IBOutlet UIBarButtonItem *previousButtonItem; IBOutlet UIBarButtonItem *nextButtonItem; id<PhotoViewDataSource> dataSource; } @property(nonatomic, retain) UIScrollView *pagingScrollView; @property(nonatomic, retain) NSMutableSet *recylcledPages; @property(nonatomic, retain) NSMutableSet *visiblePages; @property(nonatomic, retain) UIToolbar *toolbar; @property(nonatomic, retain) UIBarButtonItem *previousButtonItem; @property(nonatomic, retain) UIBarButtonItem *nextButtonItem; @property(nonatomic, retain) id<PhotoViewDataSource> dataSource;
PhotoViewController.m
- (void)loadView { self.wantsFullScreenLayout = YES; // Configure the scrollView CGRect pagingScrollViewFrame = [self frameForPagingScrollView]; pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame]; pagingScrollView.pagingEnabled = YES; pagingScrollView.backgroundColor = [UIColor redColor]; pagingScrollView.showsVerticalScrollIndicator = NO; pagingScrollView.showsHorizontalScrollIndicator = NO; pagingScrollView.contentSize = CGSizeMake(pagingScrollViewFrame.size.width * [self.dataSource imageCount], pagingScrollViewFrame.size.height); //pagingScrollView.contentOffset = CGPointMake(0, 0); pagingScrollView.delegate = self; self.view = pagingScrollView; // TODO ? Prepare to tile content recycledPages = [[NSMutableSet alloc] init]; visiblePages = [[NSMutableSet alloc] init]; [self processPages]; } - (void)processPages { // Calculate which pages are visible CGRect visibleBounds = pagingScrollView.bounds; NSLog(@"PhotoViewController - processPages : frame = %@", NSStringFromCGRect(pagingScrollView.frame)); NSLog(@"pagingScrollView bounds = %@", NSStringFromCGRect(pagingScrollView.bounds)); NSLog(@"and contentSize = %@", NSStringFromCGSize(pagingScrollView.contentSize)); int firstNeededPageIndex = floorf(CGRectGetMinX(visibleBounds) / CGRectGetWidth(visibleBounds)); int lastNeededPageIndex = floorf((CGRectGetMaxX(visibleBounds)-1) / CGRectGetWidth(visibleBounds)); firstNeededPageIndex = MAX(firstNeededPageIndex, 0); lastNeededPageIndex = MIN(lastNeededPageIndex, [dataSource imageCount] - 1); if (lastNeededPageIndex >= 0) { // 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]; // add missing pages for (int index = firstNeededPageIndex; index <= lastNeededPageIndex; index++) { if (![self isDisplayingPageForIndex:index]) { ImageScrollView *page = [self dequeueRecycledPage]; if (page == nil) { page = [[[ImageScrollView alloc] init] autorelease]; } [self configurePage:page forIndex:index]; NSLog(@"PhotoViewController - processPage 2 : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds)); [pagingScrollView addSubview:page]; NSLog(@"PhotoViewController - processPage 3 : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds)); [visiblePages addObject:page]; } } } } - (ImageScrollView *)dequeueRecycledPage { ImageScrollView *page = [recycledPages anyObject]; if (page) { [[page retain] autorelease]; [recycledPages removeObject:page]; } return page; } - (BOOL)isDisplayingPageForIndex:(NSUInteger)index { BOOL foundPage = NO; for (ImageScrollView *page in visiblePages) { if (page.index == index) { foundPage = YES; break; } } return foundPage; } - (void)configurePage:(ImageScrollView *)page forIndex:(NSUInteger)index { page.index = index; page.frame = [self frameForPageAtIndex:index]; NSLog(@"PhotoViewController - configurePage : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds)); [page displayImage:[dataSource imageForImageId:index]]; NSLog(@"PhotoViewController - configurePage 2 : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds)); }
ImageScrollView.h
@interface ImageScrollView : UIScrollView <UIScrollViewDelegate> { UIView *imageView; NSUInteger index; } @property (assign) NSUInteger index; - (void)displayImage:(UIImage *)image;
ImageScrollView.m
- (void)layoutSubviews { [super layoutSubviews]; imageView.backgroundColor = [UIColor greenColor]; self.backgroundColor = [UIColor blueColor];
My problem is that the pagingScrollView is shifted to the origin (0, -64) of the pixels (status bar height + navigation bar, I suppose) when I first load the instance of PhotoViewController. This leads to a ruined interface in which ImageScrollView appears under the navigation bar (start (0, 0)), and then can scroll up and down even when its height is smaller than the screen.
With some logs and breakpoints, I was able to determine that the boundaries of the pagingScrollView are good at the beginning of the loading process. They change when I scale the ImageScrollView image to fit the screen. This calls viewForZoomingInScrollView, and then calls the scrollViewDidScroll methods. PagingScrollView shifts during these calls.
I tried to set the offset manually, but when I do this in processPages, scrollView can no longer bounce up and down ...
Any help would be appreciated!
Greetings
RV