Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix CollectionView scroll behaviour when section is empty #808

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ The changelog for `IGListKit`. Also see the [releases](https://github.com/instag
- Prevent a crash when update queued immediately after item batch update. [Ryan Nystrom](https://github.com/rnystrom) (tbd)
- Return correct `-[IGListAdapter visibleSectionControllers]` when section has no items, but has supplementary views. [Mani Ghasemlou](https://github.com/manicakes) [(#643)](https://github.com/Instagram/IGListKit/issues/643)
- Call `[CATransaction commit]` before calling completion block in IGListAdapterUpdater to prevent animation issues. [Maxime Ollivier](https://github.com/maxoll) (tbd)
- Fix `scrollToObject:supplementaryKinds:...` not scrolling when section is empty but does have supplymentary views

### Enhancements

Expand Down
29 changes: 20 additions & 9 deletions Source/IGListAdapter.m
Original file line number Diff line number Diff line change
Expand Up @@ -172,21 +172,33 @@ - (void)scrollToObject:(id)object
}

UICollectionView *collectionView = self.collectionView;
const NSInteger numberOfItems = [collectionView numberOfItemsInSection:section];
if (numberOfItems == 0) {
return;
}

UICollectionViewLayout *layout = self.collectionView.collectionViewLayout;

// force layout before continuing
// this method is typcially called before pushing a view controller
// thus, before the layout process has actually happened
[collectionView layoutIfNeeded];

NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:section];

// collect the layout attributes for the cell and supplementary views for the first index
// this will break if there are supplementary views beyond item 0
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:section];
NSArray *attributes = [self layoutAttributesForIndexPath:indexPath supplementaryKinds:supplementaryKinds];

NSArray *attributes = nil;

const NSInteger numberOfItems = [collectionView numberOfItemsInSection:section];
if (numberOfItems > 0) {
attributes = [self layoutAttributesForIndexPath:indexPath supplementaryKinds:supplementaryKinds];
} else {
NSMutableArray *supplementaryAttributes = [NSMutableArray new];
for (NSString* supplementaryKind in supplementaryKinds) {
UICollectionViewLayoutAttributes *supplementaryAttribute = [layout layoutAttributesForSupplementaryViewOfKind:supplementaryKind atIndexPath:indexPath];
if (supplementaryAttribute != nil) {
[supplementaryAttributes addObject: supplementaryAttribute];
}
}
attributes = supplementaryAttributes;
}

CGFloat offsetMin = 0.0;
CGFloat offsetMax = 0.0;
for (UICollectionViewLayoutAttributes *attribute in attributes) {
Expand Down Expand Up @@ -715,7 +727,6 @@ - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL
}
}


#pragma mark - IGListCollectionContext

- (CGSize)containerSize {
Expand Down
37 changes: 37 additions & 0 deletions Tests/IGListAdapterTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,43 @@ - (void)test_whenScrollVerticallyToItem {
IGAssertEqualPoint([self.collectionView contentOffset], 0, 60);
}

- (void)test_whenScrollVerticallyToItemInASectionWithNoCellsAndNoSupplymentaryView {
self.dataSource.objects = @[@1, @0, @300];
[self.adapter reloadDataWithCompletion:nil];
XCTAssertEqual([self.collectionView numberOfSections], 3);
[self.adapter scrollToObject:@1 supplementaryKinds:nil scrollDirection:UICollectionViewScrollDirectionVertical scrollPosition:UICollectionViewScrollPositionNone animated:NO];
IGAssertEqualPoint([self.collectionView contentOffset], 0, 0);
[self.adapter scrollToObject:@0 supplementaryKinds:nil scrollDirection:UICollectionViewScrollDirectionVertical scrollPosition:UICollectionViewScrollPositionNone animated:NO];
IGAssertEqualPoint([self.collectionView contentOffset], 0, 0);
[self.adapter scrollToObject:@300 supplementaryKinds:nil scrollDirection:UICollectionViewScrollDirectionVertical scrollPosition:UICollectionViewScrollPositionNone animated:NO];
IGAssertEqualPoint([self.collectionView contentOffset], 0, 10);
}

- (void)test_whenScrollVerticallyToItemInASectionWithNoCellsButAHeaderSupplymentaryView {
self.dataSource.objects = @[@1, @0, @300];
[self.adapter reloadDataWithCompletion:nil];

IGTestSupplementarySource *supplementarySource = [IGTestSupplementarySource new];
supplementarySource.collectionContext = self.adapter;
supplementarySource.supportedElementKinds = @[UICollectionElementKindSectionHeader];

IGListSectionController *controller = [self.adapter sectionControllerForObject:@0];
controller.supplementaryViewSource = supplementarySource;
supplementarySource.sectionController = controller;

[self.adapter performUpdatesAnimated:NO completion:nil];

XCTAssertEqual([self.collectionView numberOfSections], 3);
[self.adapter scrollToObject:@1 supplementaryKinds:nil scrollDirection:UICollectionViewScrollDirectionVertical scrollPosition:UICollectionViewScrollPositionNone animated:NO];
IGAssertEqualPoint([self.collectionView contentOffset], 0, 0);
[self.adapter scrollToObject:@0 supplementaryKinds:nil scrollDirection:UICollectionViewScrollDirectionVertical scrollPosition:UICollectionViewScrollPositionNone animated:NO];
IGAssertEqualPoint([self.collectionView contentOffset], 0, 0);
[self.adapter scrollToObject:@0 supplementaryKinds:@[UICollectionElementKindSectionHeader] scrollDirection:UICollectionViewScrollDirectionVertical scrollPosition:UICollectionViewScrollPositionTop animated:NO];
IGAssertEqualPoint([self.collectionView contentOffset], 0, 10);
[self.adapter scrollToObject:@300 supplementaryKinds:nil scrollDirection:UICollectionViewScrollDirectionVertical scrollPosition:UICollectionViewScrollPositionNone animated:NO];
IGAssertEqualPoint([self.collectionView contentOffset], 0, 20);
}

- (void)test_whenScrollHorizontallyToItem {
// # of items for each object == [item integerValue], so @2 has 2 items (cells)
IGListTestAdapterHorizontalDataSource *dataSource = [[IGListTestAdapterHorizontalDataSource alloc] init];
Expand Down