Skip to content

Commit

Permalink
Fix CollectionView scroll behaviour when section is empty
Browse files Browse the repository at this point in the history
Summary:
Issue fixed: When a section is empty (0 cells) but has a header/footer supplementary views, calling `scrollToObject:supplementaryKinds:scrollDirection:scrollPosition:animated` wouldn't do anything as the method implementation has an early return if the section doesn't have any cells:
![screen shot 2017-06-15 at 14 07 18](https://user-images.githubusercontent.com/978865/27195239-fd86401e-51d3-11e7-8630-a018fbba6858.png)

As the section does have supplementary views and is displayed on screen, there's no reason not to scroll to it. This minor change fixes this detail.

Change in internal implementation of one method - all current tests pass. No tests added.

- [x] All tests pass. Demo project builds and runs.
- [x] I added tests, an experiment, or detailed why my change isn't tested.
- [x] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes.
- [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md)
Closes #808

Differential Revision: D5353285

Pulled By: rnystrom

fbshipit-source-id: 2b6700f98f7d38716d655dfecceb0353d65ef681
  • Loading branch information
gmoledina authored and facebook-github-bot committed Aug 11, 2017
1 parent 0a292a8 commit e8ddaf8
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
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

0 comments on commit e8ddaf8

Please sign in to comment.