Skip to content

Commit

Permalink
ASCollectionLayout improvements
Browse files Browse the repository at this point in the history
- During the first layout calculation, measure more than just elements in the visible viewport.
- Remove unnecessary params in `-[ASCollectionLayoutState getAndRemoveUnmeasuredLayoutAttributesPageTableInRect`.]
  • Loading branch information
nguyenhuy committed Aug 17, 2017
1 parent 46e9494 commit 1f6488a
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 13 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- Negate iOS 11 automatic estimated table row heights. [Christian Selig](https://github.com/christianselig) [#485](https://github.com/TextureGroup/Texture/pull/485)
- [Breaking] Add content offset bridging property to ASTableNode and ASCollectionNode. Deprecate related methods in ASTableView and ASCollectionView [Huy Nguyen](https://github.com/nguyenhuy) [#460](https://github.com/TextureGroup/Texture/pull/460)
- Remove re-entrant access to self.view when applying initial pending state. [Adlai Holler](https://github.com/Adlai-Holler) [#510](https://github.com/TextureGroup/Texture/pull/510)
- Small improvements in ASCollectionLayout [Huy Nguyen](https://github.com/nguyenhuy) [#509](https://github.com/TextureGroup/Texture/pull/509)
- Small improvements in ASCollectionLayout [Huy Nguyen](https://github.com/nguyenhuy) [#509](https://github.com/TextureGroup/Texture/pull/509) [#513](https://github.com/TextureGroup/Texture/pull/513)

##2.4
- Fix an issue where inserting/deleting sections could lead to inconsistent supplementary element behavior. [Adlai Holler](https://github.com/Adlai-Holler)
Expand Down
5 changes: 3 additions & 2 deletions Source/Details/ASCollectionLayoutState.mm
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,10 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForElement:(ASCollectionEl
}

- (ASPageToLayoutAttributesTable *)getAndRemoveUnmeasuredLayoutAttributesPageTableInRect:(CGRect)rect
contentSize:(CGSize)contentSize
pageSize:(CGSize)pageSize
{
CGSize pageSize = _context.viewportSize;
CGSize contentSize = _contentSize;

ASDN::MutexLocker l(__instanceLock__);
if (_unmeasuredPageToLayoutAttributesTable.count == 0 || CGRectIsNull(rect) || CGRectIsEmpty(rect) || CGSizeEqualToSize(CGSizeZero, contentSize) || CGSizeEqualToSize(CGSizeZero, pageSize)) {
return nil;
Expand Down
16 changes: 9 additions & 7 deletions Source/Private/ASCollectionLayout.mm
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,19 @@ + (ASCollectionLayoutState *)calculateLayoutWithContext:(ASCollectionLayoutConte
ASCollectionLayoutState *layout = [context.layoutDelegateClass calculateLayoutWithContext:context];
[context.layoutCache setLayout:layout forContext:context];

// Measure elements in the measure range ahead of time, block on the initial rect as it'll be visible shortly
// Measure elements in the measure range ahead of time
CGSize viewportSize = context.viewportSize;
CGPoint contentOffset = context.initialContentOffset;
CGRect initialRect = CGRectMake(contentOffset.x, contentOffset.y, viewportSize.width, viewportSize.height);
CGRect measureRect = CGRectExpandToRangeWithScrollableDirections(initialRect,
kASDefaultMeasureRangeTuningParameters,
context.scrollableDirections,
kASStaticScrollDirection);
[self _measureElementsInRect:measureRect blockingRect:initialRect layout:layout];
// The first call to -layoutAttributesForElementsInRect: will be with a rect that is way bigger than initialRect here.
// If we only block on initialRect, a few elements that are outside of initialRect but inside measureRect
// may not be available by the time -layoutAttributesForElementsInRect: is called.
// Since this method is usually run off main, let's spawn more threads to measure and block on all elements in measureRect.
[self _measureElementsInRect:measureRect blockingRect:measureRect layout:layout];

return layout;
}
Expand Down Expand Up @@ -248,18 +252,16 @@ + (void)_measureElementsInRect:(CGRect)rect blockingRect:(CGRect)blockingRect la
}

// Step 2: Get layout attributes of all elements within the specified outer rect
ASCollectionLayoutContext *context = layout.context;
CGSize pageSize = context.viewportSize;
ASPageToLayoutAttributesTable *attrsTable = [layout getAndRemoveUnmeasuredLayoutAttributesPageTableInRect:rect
contentSize:contentSize
pageSize:pageSize];
ASPageToLayoutAttributesTable *attrsTable = [layout getAndRemoveUnmeasuredLayoutAttributesPageTableInRect:rect];
if (attrsTable.count == 0) {
// No elements in this rect! Bail early
return;
}

// Step 3: Split all those attributes into blocking and non-blocking buckets
// Use ordered sets here because some items may span multiple pages, and the sets will be accessed by indexes later on.
ASCollectionLayoutContext *context = layout.context;
CGSize pageSize = context.viewportSize;
NSMutableOrderedSet<UICollectionViewLayoutAttributes *> *blockingAttrs = hasBlockingRect ? [NSMutableOrderedSet orderedSet] : nil;
NSMutableOrderedSet<UICollectionViewLayoutAttributes *> *nonBlockingAttrs = [NSMutableOrderedSet orderedSet];
for (id pagePtr in attrsTable) {
Expand Down
4 changes: 1 addition & 3 deletions Source/Private/ASCollectionLayoutState+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @discussion This method is atomic and thread-safe
*/
- (nullable ASPageToLayoutAttributesTable *)getAndRemoveUnmeasuredLayoutAttributesPageTableInRect:(CGRect)rect
contentSize:(CGSize)contentSize
pageSize:(CGSize)pageSize;
- (nullable ASPageToLayoutAttributesTable *)getAndRemoveUnmeasuredLayoutAttributesPageTableInRect:(CGRect)rect;

@end

Expand Down

0 comments on commit 1f6488a

Please sign in to comment.