diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index abf25ec809..f5e320fd3b 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -34,6 +34,13 @@ */ @property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters; +/** + * @abstract An optional block which can perform custom calculation for working range. + * + * @discussion Can be used to provide custom working range logic for custom layouts. + */ +@property (nonatomic, assign) asrangecontroller_working_range_calculation_block_t workingRangeCalculationBlock; + /** * Reload everything from scratch, destroying the working range and all cached nodes. * diff --git a/AsyncDisplayKit/ASCollectionView.m b/AsyncDisplayKit/ASCollectionView.m index 83b9020a8d..2ab06ff1c4 100644 --- a/AsyncDisplayKit/ASCollectionView.m +++ b/AsyncDisplayKit/ASCollectionView.m @@ -165,6 +165,16 @@ static BOOL _isInterceptedSelector(SEL sel) _rangeController.tuningParameters = tuningParameters; } +- (asrangecontroller_working_range_calculation_block_t)workingRangeCalculationBlock +{ + return _rangeController.workingRangeCalculationBlock; +} + +- (void)setWorkingRangeCalculationBlock:(asrangecontroller_working_range_calculation_block_t)workingRangeCalculationBlock +{ + _rangeController.workingRangeCalculationBlock = workingRangeCalculationBlock; +} + - (void)appendNodesWithIndexPaths:(NSArray *)indexPaths { [_rangeController appendNodesWithIndexPaths:indexPaths]; diff --git a/AsyncDisplayKit/Details/ASRangeController.h b/AsyncDisplayKit/Details/ASRangeController.h index 0629c14ac2..201fdb3fc3 100644 --- a/AsyncDisplayKit/Details/ASRangeController.h +++ b/AsyncDisplayKit/Details/ASRangeController.h @@ -16,6 +16,13 @@ typedef struct { CGFloat leadingBufferScreenfuls; } ASRangeTuningParameters; +typedef NS_ENUM(NSInteger, ASScrollDirection) { + ASScrollDirectionBackward, + ASScrollDirectionForward, +}; + +typedef NSRange (^asrangecontroller_working_range_calculation_block_t)(ASRangeTuningParameters params, ASScrollDirection scrollDirection, NSRange visibleRange, NSArray *nodeSizes, CGSize viewport); + @protocol ASRangeControllerDelegate; @@ -99,6 +106,13 @@ typedef struct { */ @property (nonatomic, assign) ASRangeTuningParameters tuningParameters; +/** + * @abstract An optional block which can perform custom calculation for working range. + * + * @discussion Can be used to provide custom working range logic for custom layouts. + */ +@property (nonatomic, readwrite, copy) asrangecontroller_working_range_calculation_block_t workingRangeCalculationBlock; + @end diff --git a/AsyncDisplayKit/Details/ASRangeController.mm b/AsyncDisplayKit/Details/ASRangeController.mm index 5019ead26e..0526ae78c7 100644 --- a/AsyncDisplayKit/Details/ASRangeController.mm +++ b/AsyncDisplayKit/Details/ASRangeController.mm @@ -13,11 +13,6 @@ #import "ASDisplayNodeInternal.h" #import "ASRangeControllerInternal.h" -typedef NS_ENUM(NSInteger, ASScrollDirection) { - ASScrollDirectionBackward, - ASScrollDirectionForward, -}; - @interface ASRangeController () { // index path -> node mapping NSMutableDictionary *_nodes; @@ -472,11 +467,21 @@ static NSRange ASCalculateWorkingRange(ASRangeTuningParameters params, ASScrollD - (void)recalculateWorkingRange { - NSRange workingRange = ASCalculateWorkingRange(_tuningParameters, - _scrollDirection, - _visibleRange, - _nodeSizes, - [_delegate rangeControllerViewportSize:self]); + NSRange workingRange; + if (self.workingRangeCalculationBlock != NULL) { + workingRange = self.workingRangeCalculationBlock(_tuningParameters, + _scrollDirection, + _visibleRange, + _nodeSizes, + [_delegate rangeControllerViewportSize:self]); + } else { + workingRange = ASCalculateWorkingRange(_tuningParameters, + _scrollDirection, + _visibleRange, + _nodeSizes, + [_delegate rangeControllerViewportSize:self]); + } + [self setWorkingRange:workingRange]; }