Skip to content

Commit

Permalink
Merge pull request #600 from georgeharker/master
Browse files Browse the repository at this point in the history
NIPagingScrollView additions
  • Loading branch information
jverkoey committed Apr 3, 2015
2 parents a94c503 + 4eeb799 commit ea00b5f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 21 deletions.
4 changes: 4 additions & 0 deletions src/pagingscrollview/src/NIPagingScrollView.h
Expand Up @@ -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
Expand Down
103 changes: 83 additions & 20 deletions src/pagingscrollview/src/NIPagingScrollView.m
Expand Up @@ -28,6 +28,7 @@

const NSInteger NIPagingScrollViewUnknownNumberOfPages = -1;
const CGFloat NIPagingScrollViewDefaultPageMargin = 10;
const CGFloat NIPagingScrollViewDefaultPageInset = 0;

@implementation NIPagingScrollView {
NIViewRecycler* _viewRecycler;
Expand All @@ -49,6 +50,7 @@ @implementation NIPagingScrollView {
- (void)commonInit {
// Default state.
self.pageMargin = NIPagingScrollViewDefaultPageMargin;
self.pageInset = NIPagingScrollViewDefaultPageInset;
self.type = NIPagingScrollViewHorizontal;

// Internal state
Expand Down Expand Up @@ -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;
Expand All @@ -137,32 +139,32 @@ - (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;
}

- (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;
}

- (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;
Expand Down Expand Up @@ -214,19 +216,42 @@ - (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);
}

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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/photos/src/NIPhotoAlbumScrollView.m
Expand Up @@ -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;
Expand Down

0 comments on commit ea00b5f

Please sign in to comment.