mirror of
https://github.com/HackPlan/AsyncDisplayKit.git
synced 2026-04-29 04:05:35 +08:00
Update ASRangeController to support ASCollectionView and no longer assume vertical scrolling when calculates working range.
This commit is contained in:
@@ -14,8 +14,8 @@
|
|||||||
#import "ASRangeControllerInternal.h"
|
#import "ASRangeControllerInternal.h"
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, ASScrollDirection) {
|
typedef NS_ENUM(NSInteger, ASScrollDirection) {
|
||||||
ASScrollDirectionUp,
|
ASScrollDirectionBackward,
|
||||||
ASScrollDirectionDown,
|
ASScrollDirectionForward,
|
||||||
};
|
};
|
||||||
|
|
||||||
@interface ASRangeController () {
|
@interface ASRangeController () {
|
||||||
@@ -283,7 +283,7 @@ static BOOL ASRangeIsValid(NSRange range)
|
|||||||
_visibleRange = _workingRange = NSMakeRange(NSNotFound, 0);
|
_visibleRange = _workingRange = NSMakeRange(NSNotFound, 0);
|
||||||
_sizedNodeCount = 0;
|
_sizedNodeCount = 0;
|
||||||
_nodeSizes = [NSMutableArray array];
|
_nodeSizes = [NSMutableArray array];
|
||||||
_scrollDirection = ASScrollDirectionDown;
|
_scrollDirection = ASScrollDirectionForward;
|
||||||
_workingIndexPaths = [NSMutableOrderedSet orderedSet];
|
_workingIndexPaths = [NSMutableOrderedSet orderedSet];
|
||||||
|
|
||||||
// don't bother sizing if the data source is empty
|
// don't bother sizing if the data source is empty
|
||||||
@@ -413,34 +413,38 @@ static NSRange ASCalculateWorkingRange(ASRangeTuningParameters params, ASScrollD
|
|||||||
ASDisplayNodeCAssert(NSMaxRange(visibleRange) <= nodeSizes.count, @"nodes can't be visible until they're sized");
|
ASDisplayNodeCAssert(NSMaxRange(visibleRange) <= nodeSizes.count, @"nodes can't be visible until they're sized");
|
||||||
|
|
||||||
// extend the visible range by enough nodes to fill at least the requested number of screenfuls
|
// extend the visible range by enough nodes to fill at least the requested number of screenfuls
|
||||||
// NB. this logic assumes (UITableView-style) vertical scrolling and would need to be changed for ASCollectionView
|
// NB. this logic assumes there is no overlap between nodes. It also doesn't
|
||||||
|
// take spacing between nodes into account.
|
||||||
|
CGFloat viewportArea = viewport.width * viewport.height;
|
||||||
CGFloat minUpperBufferSize, minLowerBufferSize;
|
CGFloat minUpperBufferSize, minLowerBufferSize;
|
||||||
switch (scrollDirection) {
|
switch (scrollDirection) {
|
||||||
case ASScrollDirectionUp:
|
case ASScrollDirectionBackward:
|
||||||
minUpperBufferSize = viewport.height * params.leadingBufferScreenfuls;
|
minUpperBufferSize = viewportArea * params.leadingBufferScreenfuls;
|
||||||
minLowerBufferSize = viewport.height * params.trailingBufferScreenfuls;
|
minLowerBufferSize = viewportArea * params.trailingBufferScreenfuls;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASScrollDirectionDown:
|
case ASScrollDirectionForward:
|
||||||
minUpperBufferSize = viewport.height * params.trailingBufferScreenfuls;
|
minUpperBufferSize = viewportArea * params.trailingBufferScreenfuls;
|
||||||
minLowerBufferSize = viewport.height * params.leadingBufferScreenfuls;
|
minLowerBufferSize = viewportArea * params.leadingBufferScreenfuls;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "top" buffer (above the screen, if we're scrolling vertically)
|
// "top" buffer (above the screen, if we're scrolling vertically)
|
||||||
NSInteger upperBuffer = 0;
|
NSInteger upperBuffer = 0;
|
||||||
CGFloat upperBufferHeight = 0.0f;
|
CGFloat upperBufferArea = 0.0f;
|
||||||
for (NSInteger idx = visibleRange.location - 1; idx >= 0 && upperBufferHeight < minUpperBufferSize; idx--) {
|
for (NSInteger idx = visibleRange.location - 1; idx >= 0 && upperBufferArea < minUpperBufferSize; idx--) {
|
||||||
upperBuffer++;
|
upperBuffer++;
|
||||||
upperBufferHeight += [nodeSizes[idx] CGSizeValue].height;
|
CGSize nodeSize = [nodeSizes[idx] CGSizeValue];
|
||||||
|
upperBufferArea += nodeSize.width * nodeSize.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "bottom" buffer (below the screen, if we're scrolling vertically)
|
// "bottom" buffer (below the screen, if we're scrolling vertically)
|
||||||
NSInteger lowerBuffer = 0;
|
NSInteger lowerBuffer = 0;
|
||||||
CGFloat lowerBufferHeight = 0.0f;
|
CGFloat lowerBufferArea = 0.0f;
|
||||||
for (NSInteger idx = NSMaxRange(visibleRange); idx < nodeSizes.count && lowerBufferHeight < minLowerBufferSize; idx++) {
|
for (NSInteger idx = NSMaxRange(visibleRange); idx < nodeSizes.count && lowerBufferArea < minLowerBufferSize; idx++) {
|
||||||
lowerBuffer++;
|
lowerBuffer++;
|
||||||
lowerBufferHeight += [nodeSizes[idx] CGSizeValue].height;
|
CGSize nodeSize = [nodeSizes[idx] CGSizeValue];
|
||||||
|
lowerBufferArea += nodeSize.width * nodeSize.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NSMakeRange(visibleRange.location - upperBuffer,
|
return NSMakeRange(visibleRange.location - upperBuffer,
|
||||||
@@ -459,9 +463,9 @@ static NSRange ASCalculateWorkingRange(ASRangeTuningParameters params, ASScrollD
|
|||||||
// figure out where we're going, because that's where the bulk of the working range needs to be
|
// figure out where we're going, because that's where the bulk of the working range needs to be
|
||||||
NSInteger scrollDelta = _visibleRange.location - previouslyVisible.location;
|
NSInteger scrollDelta = _visibleRange.location - previouslyVisible.location;
|
||||||
if (scrollDelta < 0)
|
if (scrollDelta < 0)
|
||||||
_scrollDirection = ASScrollDirectionUp;
|
_scrollDirection = ASScrollDirectionBackward;
|
||||||
if (scrollDelta > 0)
|
if (scrollDelta > 0)
|
||||||
_scrollDirection = ASScrollDirectionDown;
|
_scrollDirection = ASScrollDirectionForward;
|
||||||
|
|
||||||
[self recalculateWorkingRange];
|
[self recalculateWorkingRange];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user