Skip to content

Commit

Permalink
added improved scrolling behavior when changing item size in grid vie…
Browse files Browse the repository at this point in the history
…w demo

When changing the item size using the slider, the view controller scrolls to either the selected cell or to what ever cell was in the center of the view. This results in more consistent behavior closer to what IKImageBrowserView does.
  • Loading branch information
Martin Hering committed Dec 31, 2014
1 parent 0baf57e commit 1a34179
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 3 deletions.
2 changes: 1 addition & 1 deletion demo/JNWCollectionViewDemo/GridDemoViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#import <Cocoa/Cocoa.h>
#import <JNWCollectionView/JNWCollectionView.h>

@interface GridDemoViewController : NSViewController <JNWCollectionViewDataSource, JNWCollectionViewGridLayoutDelegate>
@interface GridDemoViewController : NSViewController

@property (nonatomic, weak) IBOutlet JNWCollectionView *collectionView;

Expand Down
66 changes: 64 additions & 2 deletions demo/JNWCollectionViewDemo/GridDemoViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
#import "GridDemoViewController.h"
#import "GridCell.h"

@interface GridDemoViewController()
@interface GridDemoViewController() <JNWCollectionViewDataSource, JNWCollectionViewDelegate, JNWCollectionViewGridLayoutDelegate>
@property (nonatomic, strong) NSArray *images;
@property (nonatomic, strong) IBOutlet NSSlider *sizeSlider;
@property (nonatomic, strong) NSIndexPath* activeScrollCellIndexPath;
@property (nonatomic, strong) NSIndexPath* selectedIndexPath;
@property (nonatomic) BOOL userScroll;
@end

static NSString * const identifier = @"CELL";
Expand All @@ -31,15 +34,63 @@ - (void)awakeFromNib {

self.collectionView.collectionViewLayout = gridLayout;
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
self.collectionView.animatesSelection = NO; // (this is the default option)

[self.collectionView registerClass:GridCell.class forCellWithReuseIdentifier:identifier];

// this is not nice, better would be to have an NSScrollViewDelegate
[[NSNotificationCenter defaultCenter] addObserverForName:NSViewBoundsDidChangeNotification
object:self.collectionView.clipView
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
// coalesced execution for better performance
if (!self.userScroll) {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_updateScrollAnchor) object:nil];
[self performSelector:@selector(_updateScrollAnchor) withObject:nil afterDelay:0.05];
}
}];

[self.collectionView reloadData];
}

- (IBAction)updateSizeSliderValue:(id)sender {
- (void) _updateScrollAnchor
{
self.activeScrollCellIndexPath = [self _centerCellIndexPath];
}

- (NSIndexPath*) _centerCellIndexPath
{
NSRect scrollRect = self.collectionView.documentVisibleRect;
// don't optimize scrolling when scrolled on top edge
if (NSMinY(scrollRect) <= 0) {
return nil;
}

NSArray* indexPathes = [self.collectionView.collectionViewLayout indexPathsForItemsInRect:scrollRect];
if ([indexPathes count] == 0) {
return nil;
}

NSUInteger middleIndex = [indexPathes count]/2;
return indexPathes[middleIndex];
}

- (IBAction)updateSizeSliderValue:(id)sender
{
//NSRect visibleScrollRect = self.collectionView.documentVisibleRect;
[self.collectionView.collectionViewLayout invalidateLayout];

NSIndexPath* scrollIndexPath = (self.selectedIndexPath) ? self.selectedIndexPath : self.activeScrollCellIndexPath;
if (scrollIndexPath) {
self.userScroll = YES;
[self.collectionView scrollToItemAtIndexPath:scrollIndexPath
atScrollPosition:JNWCollectionViewScrollPositionMiddle
animated:NO];
self.userScroll = NO;
}


}

#pragma mark Data source
Expand All @@ -63,6 +114,17 @@ - (CGSize)sizeForItemInCollectionView:(JNWCollectionView *)collectionView {
return CGSizeMake(sizeSliderValue, sizeSliderValue);
}

- (void)collectionView:(JNWCollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedIndexPath = indexPath;
}

- (void)collectionView:(JNWCollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
if ([self.selectedIndexPath isEqualTo:indexPath]) {
self.selectedIndexPath = nil;
}
}
#pragma mark Image creation

// To simulate at least something realistic, this just generates some randomly tinted images so that not every
Expand Down

0 comments on commit 1a34179

Please sign in to comment.