diff --git a/src/pagingscrollview/src/NIPagingScrollView.h b/src/pagingscrollview/src/NIPagingScrollView.h index 181452e25..7382d7a04 100644 --- a/src/pagingscrollview/src/NIPagingScrollView.h +++ b/src/pagingscrollview/src/NIPagingScrollView.h @@ -68,7 +68,11 @@ typedef enum { #pragma mark Configuring Presentation +// Controls the border between images. @property (nonatomic) CGFloat pageMargin; +// Used to make the view smaller than full screen, thus showing neighboring images +// in the view. +@property (nonatomic) CGFloat pageInset; @property (nonatomic) NIPagingScrollViewType type; // Default: NIPagingScrollViewHorizontal #pragma mark Visible Pages diff --git a/src/pagingscrollview/src/NIPagingScrollView.m b/src/pagingscrollview/src/NIPagingScrollView.m index 87ae05729..a0414b113 100644 --- a/src/pagingscrollview/src/NIPagingScrollView.m +++ b/src/pagingscrollview/src/NIPagingScrollView.m @@ -28,6 +28,7 @@ const NSInteger NIPagingScrollViewUnknownNumberOfPages = -1; const CGFloat NIPagingScrollViewDefaultPageMargin = 10; +const CGFloat NIPagingScrollViewDefaultPageInset = 0; @implementation NIPagingScrollView { NIViewRecycler* _viewRecycler; @@ -49,6 +50,7 @@ @implementation NIPagingScrollView { - (void)commonInit { // Default state. self.pageMargin = NIPagingScrollViewDefaultPageMargin; + self.pageInset = NIPagingScrollViewDefaultPageInset; self.type = NIPagingScrollViewHorizontal; // Internal state @@ -119,14 +121,14 @@ - (CGRect)frameForPageAtIndex:(NSInteger)pageIndex { CGRect pageFrame = bounds; if (NIPagingScrollViewHorizontal == self.type) { - pageFrame.origin.x = (bounds.size.width * pageIndex); + pageFrame.origin.x = ((bounds.size.width - self.pageInset * 2) * pageIndex); // We need to counter the extra spacing added to the paging scroll view in // frameForPagingScrollView. - pageFrame = CGRectInset(pageFrame, self.pageMargin, 0); + pageFrame = CGRectInset(pageFrame, self.pageMargin + self.pageInset, 0); } else if (NIPagingScrollViewVertical == self.type) { - pageFrame.origin.y = (bounds.size.height * pageIndex); - pageFrame = CGRectInset(pageFrame, 0, self.pageMargin); + pageFrame.origin.y = ((bounds.size.height - self.pageInset * 2) * pageIndex); + pageFrame = CGRectInset(pageFrame, 0, self.pageMargin + self.pageInset); } return pageFrame; @@ -137,10 +139,10 @@ - (CGSize)contentSizeForPagingScrollView { // outlined above. CGRect bounds = _scrollView.bounds; if (NIPagingScrollViewHorizontal == self.type) { - return CGSizeMake(bounds.size.width * self.numberOfPages, bounds.size.height); + return CGSizeMake((bounds.size.width - self.pageInset * 2) * self.numberOfPages, bounds.size.height); } else if (NIPagingScrollViewVertical == self.type) { - return CGSizeMake(bounds.size.width, bounds.size.height * self.numberOfPages); + return CGSizeMake(bounds.size.width, (bounds.size.height - self.pageInset * 2) * self.numberOfPages); } return CGSizeZero; @@ -148,10 +150,10 @@ - (CGSize)contentSizeForPagingScrollView { - (CGPoint)contentOffsetFromPageOffset:(CGPoint)offset { if (NIPagingScrollViewHorizontal == self.type) { - offset.x -= self.pageMargin; + offset.x -= self.pageMargin + self.pageInset; } else if (NIPagingScrollViewVertical == self.type) { - offset.y -= self.pageMargin; + offset.y -= self.pageMargin + self.pageInset; } return offset; @@ -159,10 +161,10 @@ - (CGPoint)contentOffsetFromPageOffset:(CGPoint)offset { - (CGFloat)pageScrollableDimension { if (NIPagingScrollViewHorizontal == self.type) { - return _scrollView.bounds.size.width; + return _scrollView.bounds.size.width - self.pageInset * 2; } else if (NIPagingScrollViewVertical == self.type) { - return _scrollView.bounds.size.height; + return _scrollView.bounds.size.height - self.pageInset * 2; } return 0; @@ -214,12 +216,14 @@ - (NSInteger)currentVisiblePageIndex { if (NIPagingScrollViewHorizontal == self.type) { // Whatever image is currently displayed in the center of the screen is the currently // visible image. - return NIBoundi((NSInteger)(NICGFloatFloor((contentOffset.x + boundsSize.width / 2) / boundsSize.width) + return NIBoundi((NSInteger)(NICGFloatFloor((contentOffset.x + boundsSize.width / 2) / + (boundsSize.width - self.pageInset * 2)) + 0.5f), 0, self.numberOfPages - 1); } else if (NIPagingScrollViewVertical == self.type) { - return NIBoundi((NSInteger)(NICGFloatFloor((contentOffset.y + boundsSize.height / 2) / boundsSize.height) + return NIBoundi((NSInteger)(NICGFloatFloor((contentOffset.y + boundsSize.height / 2) / + (boundsSize.height - self.pageInset * 2)) + 0.5f), 0, self.numberOfPages - 1); } @@ -227,6 +231,27 @@ - (NSInteger)currentVisiblePageIndex { return 0; } +- (NSInteger)pageIndexForOffset:(CGFloat)offset { + CGSize boundsSize = _scrollView.bounds.size; + + if (NIPagingScrollViewHorizontal == self.type) { + // Whatever image is currently displayed in the center of the screen is the currently + // visible image. + return NIBoundi((NSInteger)(NICGFloatFloor((offset + boundsSize.width / 2) / + (boundsSize.width - self.pageInset * 2)) + + 0.5f), + 0, self.numberOfPages - 1); + + } else if (NIPagingScrollViewVertical == self.type) { + return NIBoundi((NSInteger)(NICGFloatFloor((offset + boundsSize.height / 2) / + (boundsSize.height - self.pageInset * 2)) + + 0.5f), + 0, self.numberOfPages - 1); + } + + return 0; +} + - (NSRange)rangeOfVisiblePages { if (0 >= self.numberOfPages) { return NSMakeRange(0, 0); @@ -350,15 +375,20 @@ - (void)updateVisiblePagesShouldNotifyDelegate:(BOOL)shouldNotifyDelegate { [self didChangeCenterPageIndexFrom:oldCenterPageIndex to:_centerPageIndex]; - // Prioritize displaying the currently visible page. - if (![self isDisplayingPageForIndex:_centerPageIndex]) { - [self displayPageAtIndex:_centerPageIndex]; + if (_pageInset != 0) { + // When multiple images are visible load them all. + [self preloadOffscreenPages]; + } else { + // Prioritize displaying the currently visible page. + if (![self isDisplayingPageForIndex:_centerPageIndex]) { + [self displayPageAtIndex:_centerPageIndex]; + } + + // Add missing pages after displaying the current page. + [self performSelector:@selector(preloadOffscreenPages) + withObject:nil + afterDelay:0]; } - - // Add missing pages after displaying the current page. - [self performSelector:@selector(preloadOffscreenPages) - withObject:nil - afterDelay:0]; } else { _centerPageIndex = -1; } @@ -393,6 +423,11 @@ - (void)setFrame:(CGRect)frame { [self layoutVisiblePages]; } +- (void)layoutSubviews { + _scrollView.contentSize = [self contentSizeForPagingScrollView]; + [self layoutVisiblePages]; +} + #pragma mark - UIScrollViewDelegate - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { @@ -440,6 +475,21 @@ - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL } } +- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset +{ + if (_pageInset == 0) { + // We handle the standard case for scrolling via pagingEnabled. + return; + } + CGFloat targetX = _scrollView.contentOffset.x + velocity.x * 60.0f; + NSInteger targetIndex = [self pageIndexForOffset:targetX]; + + CGPoint offset = [self frameForPageAtIndex:targetIndex].origin; + offset = [self contentOffsetFromPageOffset:offset]; + + *targetContentOffset = offset; +} + - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { [self updateVisiblePagesShouldNotifyDelegate:YES]; [self resetSurroundingPages]; @@ -694,6 +744,19 @@ - (void)setPageMargin:(CGFloat)pageMargin { [self setNeedsLayout]; } +- (void)setPageInset:(CGFloat)pageInset { + _pageInset = pageInset; + // Do not auto-page inset views. The paging is based on view bounds, + // which would not be correct. We compute the snapping manually. + _scrollView.pagingEnabled = (_pageInset == 0); + + // Retain the current position. + CGPoint offset = [self frameForPageAtIndex:_centerPageIndex].origin; + _scrollView.contentOffset = [self contentOffsetFromPageOffset:offset]; + + [self setNeedsLayout]; +} + - (void)setType:(NIPagingScrollViewType)type { if (_type != type) { _type = type; diff --git a/src/photos/src/NIPhotoAlbumScrollView.m b/src/photos/src/NIPhotoAlbumScrollView.m index 64acd2109..79709d47c 100644 --- a/src/photos/src/NIPhotoAlbumScrollView.m +++ b/src/photos/src/NIPhotoAlbumScrollView.m @@ -80,7 +80,8 @@ - (void)willDisplayPage:(NIPhotoScrollView *)page { originalPhotoDimensions: &originalPhotoDimensions]; page.photoDimensions = originalPhotoDimensions; - page.loading = isLoading; + // Only mark the view as loading if the center image is loading. + page.loading = (page.pageIndex == self.centerPageIndex) && isLoading; if (nil == image) { page.zoomingIsEnabled = NO;