Fixed empty space bug in CollectionView

Summary:
Fixed situation when cells with small height don't intersect with the _Rect_ and stop the enumeration that cause empty spaces in _collectionView_.

Issue fixed: # [680](https://github.com/Instagram/IGListKit/issues/680)

- [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 https://github.com/Instagram/IGListKit/pull/684

Differential Revision: D4929315

Pulled By: rnystrom

fbshipit-source-id: 4437df21772697a9a6421d213f4fed7b8470371b
This commit is contained in:
Artem Goncharov 2017-04-21 08:11:44 -07:00 committed by Facebook Github Bot
parent fdbe025fe1
commit e729ab8211
2 changed files with 59 additions and 10 deletions

View file

@ -123,10 +123,6 @@ static void adjustZIndexForAttributes(UICollectionViewLayoutAttributes *attribut
NSMutableArray *result = [NSMutableArray new];
// since we iterate through sections ascending, we may hit a section who is only partially visible
// in that case we short circuit building layout attributes
BOOL remainingCellsOutOfRect = NO;
const NSRange range = [self rangeOfSectionsInRect:rect];
if (range.location == NSNotFound) {
return nil;
@ -152,12 +148,7 @@ static void adjustZIndexForAttributes(UICollectionViewLayoutAttributes *attribut
for (NSInteger item = 0; item < itemCount; item++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item inSection:section];
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
if (!CGRectIntersectsRect(attributes.frame, rect)) {
if (remainingCellsOutOfRect) {
return result;
}
} else {
remainingCellsOutOfRect = YES;
if (CGRectIntersectsRect(attributes.frame, rect)) {
[result addObject:attributes];
}
}

View file

@ -520,6 +520,64 @@ static const CGRect kTestFrame = (CGRect){{0, 0}, {100, 100}};
XCTAssertEqual([self.layout layoutAttributesForElementsInRect:CGRectMake(0, 250, 100, 1)].count, 1);
}
- (void)test_whenSecondItemDoesntIntersectRect_thatOtherAttributesExist {
[self setUpWithStickyHeaders:NO topInset:0];
NSMutableArray *data = [NSMutableArray new];
for (NSInteger i = 0; i < 6; i++) {
[data addObject:[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize){50, 100}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize){50, 10}],
]]];
}
[self prepareWithData:data];
NSArray *attributes = [self.layout layoutAttributesForElementsInRect:CGRectMake(0, 50, 100, 100)];
NSArray *paths = [[attributes valueForKeyPath:@"indexPath"] sortedArrayUsingSelector:@selector(compare:)];
NSArray *expectation = @[
genIndexPath(0, 0),
genIndexPath(1, 0),
genIndexPath(1, 1),
];
// should include 2 of the 100-height items and one of the 10-height
XCTAssertEqualObjects(paths, expectation);
}
- (void)test_whenTwoConsecutiveItemsDontIntersectRect_thatOtherAttributesExist {
[self setUpWithStickyHeaders:NO topInset:0];
NSMutableArray *data = [NSMutableArray new];
for (NSInteger i = 0; i < 6; i++) {
[data addObject:[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize){30, 100}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize){30, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize){30, 10}],
]]];
}
[self prepareWithData:data];
NSArray *attributes = [self.layout layoutAttributesForElementsInRect:CGRectMake(0, 50, 100, 100)];
NSArray *paths = [[attributes valueForKeyPath:@"indexPath"] sortedArrayUsingSelector:@selector(compare:)];
NSArray *expectation = @[
genIndexPath(0, 0),
genIndexPath(1, 0),
genIndexPath(1, 1),
genIndexPath(1, 2),
];
// should include 2 of the 100-height items and two of the 10-height
XCTAssertEqualObjects(paths, expectation);
}
- (void)test_whenChangingBoundsSize_withItemsThatNewlineAfterChange_thatLayoutShiftsItems {
[self setUpWithStickyHeaders:NO topInset:0];