Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ASTableNode][ASCollectionNode] Add content offset bridging property #460

Merged
merged 8 commits into from
Aug 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Fix an issue that causes calculatedLayoutDidChange being called needlessly. [Huy Nguyen](https://github.com/nguyenhuy) [#490](https://github.com/TextureGroup/Texture/pull/490)
- Negate iOS 11 automatic estimated table row heights. [Christian Selig](https://github.com/christianselig) [#485](https://github.com/TextureGroup/Texture/pull/485)
- Rename ASCellNode.viewModel to ASCellNode.nodeViewModel to reduce collisions with subclass properties implemented by clients. [Adlai Holler](https://github.com/Adlai-Holler) [#499](https://github.com/TextureGroup/Texture/pull/499)
- [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)

##2.3.5
- Fix an issue where inserting/deleting sections could lead to inconsistent supplementary element behavior. [Adlai Holler](https://github.com/Adlai-Holler)
Expand Down
14 changes: 14 additions & 0 deletions Source/ASCollectionNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, weak) id<ASCollectionViewLayoutInspecting> layoutInspector;

/**
* The offset of the content view's origin from the collection node's origin. Defaults to CGPointZero.
*/
@property (nonatomic, assign) CGPoint contentOffset;

/**
* Sets the offset from the content node’s origin to the collection node’s origin.
*
* @param contentOffset The offset
*
* @param animated YES to animate to this new offset at a constant velocity, NO to not aniamte and immediately make the transition.
*/
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;

/**
* Tuning parameters for a range type in full mode.
*
Expand Down
30 changes: 30 additions & 0 deletions Source/ASCollectionNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ @interface _ASCollectionPendingState : NSObject
@property (nonatomic, assign) BOOL usesSynchronousDataLoading;
@property (nonatomic, assign) CGFloat leadingScreensForBatching;
@property (weak, nonatomic) id <ASCollectionViewLayoutInspecting> layoutInspector;
@property (nonatomic, assign) CGPoint contentOffset;
@property (nonatomic, assign) BOOL animatesContentOffset;
@end

@implementation _ASCollectionPendingState
Expand All @@ -61,6 +63,8 @@ - (instancetype)init
_allowsSelection = YES;
_allowsMultipleSelection = NO;
_inverted = NO;
_contentOffset = CGPointZero;
_animatesContentOffset = NO;
}
return self;
}
Expand Down Expand Up @@ -189,6 +193,8 @@ - (void)didLoad
if (pendingState.rangeMode != ASLayoutRangeModeUnspecified) {
[view.rangeController updateCurrentRangeWithMode:pendingState.rangeMode];
}

[view setContentOffset:pendingState.contentOffset animated:pendingState.animatesContentOffset];

// Don't need to set collectionViewLayout to the view as the layout was already used to init the view in view block.
}
Expand Down Expand Up @@ -434,6 +440,30 @@ - (UICollectionViewLayout *)collectionViewLayout
}
}

- (void)setContentOffset:(CGPoint)contentOffset
{
[self setContentOffset:contentOffset animated:NO];
}

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
{
if ([self pendingState]) {
_pendingState.contentOffset = contentOffset;
_pendingState.animatesContentOffset = animated;
} else {
[self.view setContentOffset:contentOffset animated:animated];
}
}

- (CGPoint)contentOffset
{
if ([self pendingState]) {
return _pendingState.contentOffset;
} else {
return self.view.contentOffset;
}
}

- (ASScrollDirection)scrollDirection
{
return [self isNodeLoaded] ? self.view.scrollDirection : ASScrollDirectionNone;
Expand Down
7 changes: 7 additions & 0 deletions Source/ASCollectionView.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic) BOOL zeroContentInsets ASDISPLAYNODE_DEPRECATED_MSG("Set automaticallyAdjustsScrollViewInsets=NO on your view controller instead.");

/**
* The point at which the origin of the content view is offset from the origin of the collection view.
*/
@property (nonatomic, assign) CGPoint contentOffset ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode property instead.");

/**
* The object that acts as the asynchronous delegate of the collection view
*
Expand Down Expand Up @@ -407,6 +412,8 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (NSArray<__kindof ASCellNode *> *)visibleNodes AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead.");

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead.");

@end

ASDISPLAYNODE_DEPRECATED_MSG("Renamed to ASCollectionDataSource.")
Expand Down
14 changes: 14 additions & 0 deletions Source/ASTableNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, assign) BOOL inverted;

/**
* The offset of the content view's origin from the table node's origin. Defaults to CGPointZero.
*/
@property (nonatomic, assign) CGPoint contentOffset;

/**
* Sets the offset from the content node’s origin to the table node’s origin.
*
* @param contentOffset The offset
*
* @param animated YES to animate to this new offset at a constant velocity, NO to not aniamte and immediately make the transition.
*/
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;

/**
* YES to automatically adjust the contentOffset when cells are inserted or deleted above
* visible cells, maintaining the users' visible scroll position.
Expand Down
32 changes: 32 additions & 0 deletions Source/ASTableNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ @interface _ASTablePendingState : NSObject
@property (nonatomic, assign) BOOL allowsMultipleSelectionDuringEditing;
@property (nonatomic, assign) BOOL inverted;
@property (nonatomic, assign) CGFloat leadingScreensForBatching;
@property (nonatomic, assign) CGPoint contentOffset;
@property (nonatomic, assign) BOOL animatesContentOffset;
@property (nonatomic, assign) BOOL automaticallyAdjustsContentOffset;
@end

Expand All @@ -58,6 +60,8 @@ - (instancetype)init
_allowsMultipleSelectionDuringEditing = NO;
_inverted = NO;
_leadingScreensForBatching = 2;
_contentOffset = CGPointZero;
_animatesContentOffset = NO;
_automaticallyAdjustsContentOffset = NO;
}
return self;
Expand Down Expand Up @@ -120,6 +124,7 @@ - (void)didLoad
if (pendingState.rangeMode != ASLayoutRangeModeUnspecified) {
[view.rangeController updateCurrentRangeWithMode:pendingState.rangeMode];
}
[view setContentOffset:pendingState.contentOffset animated:pendingState.animatesContentOffset];
}
}

Expand Down Expand Up @@ -232,6 +237,33 @@ - (CGFloat)leadingScreensForBatching
}
}

- (void)setContentOffset:(CGPoint)contentOffset
{
[self setContentOffset:contentOffset animated:NO];
}

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
{
_ASTablePendingState *pendingState = self.pendingState;
if (pendingState) {
pendingState.contentOffset = contentOffset;
pendingState.animatesContentOffset = animated;
} else {
ASDisplayNodeAssert(self.nodeLoaded, @"ASTableNode should be loaded if pendingState doesn't exist");
[self.view setContentOffset:contentOffset animated:animated];
}
}

- (CGPoint)contentOffset
{
_ASTablePendingState *pendingState = self.pendingState;
if (pendingState) {
return pendingState.contentOffset;
} else {
return self.view.contentOffset;
}
}

- (void)setAutomaticallyAdjustsContentOffset:(BOOL)automaticallyAdjustsContentOffset
{
_ASTablePendingState *pendingState = self.pendingState;
Expand Down
18 changes: 12 additions & 6 deletions Source/ASTableView.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, assign) CGFloat leadingScreensForBatching ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode property instead.");

/**
* The offset of the content view's origin from the table node's origin. Defaults to CGPointZero.
*/
@property (nonatomic, assign) CGPoint contentOffset ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode property instead.");

/**
* YES to automatically adjust the contentOffset when cells are inserted or deleted above
Expand All @@ -84,6 +88,12 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, assign) BOOL inverted ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode property instead.");

@property (nonatomic, readonly, nullable) NSIndexPath *indexPathForSelectedRow ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode property instead.");

@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForSelectedRows ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode property instead.");

@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForVisibleRows ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode property instead.");

/**
* Tuning parameters for a range type in full mode.
*
Expand Down Expand Up @@ -138,12 +148,6 @@ NS_ASSUME_NONNULL_BEGIN

- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead.");

@property (nonatomic, readonly, nullable) NSIndexPath *indexPathForSelectedRow ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode property instead.");

@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForSelectedRows ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode property instead.");

@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForVisibleRows ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode property instead.");

- (nullable NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead.");

- (nullable NSArray<NSIndexPath *> *)indexPathsForRowsInRect:(CGRect)rect ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead.");
Expand Down Expand Up @@ -241,6 +245,8 @@ NS_ASSUME_NONNULL_BEGIN
/// Deprecated in 2.0. You should not call this method.
- (void)clearFetchedData ASDISPLAYNODE_DEPRECATED_MSG("You should not call this method directly. Intead, rely on the Interstate State callback methods.");

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead.");

@end

ASDISPLAYNODE_DEPRECATED_MSG("Renamed to ASTableDataSource.")
Expand Down
1 change: 1 addition & 0 deletions Source/Details/ASCollectionLayoutContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ AS_SUBCLASSING_RESTRICTED
@interface ASCollectionLayoutContext : NSObject

@property (nonatomic, assign, readonly) CGSize viewportSize;
@property (nonatomic, assign, readonly) CGPoint initialContentOffset;
@property (nonatomic, assign, readonly) ASScrollDirection scrollableDirections;
@property (nonatomic, weak, readonly) ASElementMap *elements;
@property (nonatomic, strong, readonly, nullable) id additionalInfo;
Expand Down
7 changes: 4 additions & 3 deletions Source/Details/ASCollectionLayoutContext.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@

@implementation ASCollectionLayoutContext {
Class<ASCollectionLayoutDelegate> _layoutDelegateClass;

// This ivar doesn't directly involve in the layout calculation process, i.e contexts can be equal regardless of the layout caches.
// As a result, this ivar is ignored in -isEqualToContext: and -hash.
__weak ASCollectionLayoutCache *_layoutCache;
}

- (instancetype)initWithViewportSize:(CGSize)viewportSize
initialContentOffset:(CGPoint)initialContentOffset
scrollableDirections:(ASScrollDirection)scrollableDirections
elements:(ASElementMap *)elements
layoutDelegateClass:(Class<ASCollectionLayoutDelegate>)layoutDelegateClass
Expand All @@ -38,6 +36,7 @@ - (instancetype)initWithViewportSize:(CGSize)viewportSize
self = [super init];
if (self) {
_viewportSize = viewportSize;
_initialContentOffset = initialContentOffset;
_scrollableDirections = scrollableDirections;
_elements = elements;
_layoutDelegateClass = layoutDelegateClass;
Expand All @@ -57,6 +56,8 @@ - (ASCollectionLayoutCache *)layoutCache
return _layoutCache;
}

// NOTE: Some properties, like initialContentOffset and layoutCache are ignored in -isEqualToContext: and -hash.
// That is because contexts can be equal regardless of the content offsets or layout caches.
- (BOOL)isEqualToContext:(ASCollectionLayoutContext *)context
{
if (context == nil) {
Expand Down
6 changes: 4 additions & 2 deletions Source/Private/ASCollectionLayout.mm
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,13 @@ - (ASCollectionLayoutContext *)layoutContextWithElements:(ASElementMap *)element
{
ASDisplayNodeAssertMainThread();
CGSize viewportSize = [self _viewportSize];
CGPoint contentOffset = _collectionNode.contentOffset;
id additionalInfo = nil;
if (_layoutDelegateFlags.implementsAdditionalInfoForLayoutWithElements) {
additionalInfo = [_layoutDelegate additionalInfoForLayoutWithElements:elements];
}
return [[ASCollectionLayoutContext alloc] initWithViewportSize:viewportSize
initialContentOffset:contentOffset
scrollableDirections:[_layoutDelegate scrollableDirections]
elements:elements
layoutDelegateClass:[_layoutDelegate class]
Expand All @@ -93,8 +95,8 @@ + (ASCollectionLayoutState *)calculateLayoutWithContext:(ASCollectionLayoutConte

// Measure elements in the measure range ahead of time, block on the initial rect as it'll be visible shortly
CGSize viewportSize = context.viewportSize;
// TODO Consider content offset of the collection node
CGRect initialRect = CGRectMake(0, 0, viewportSize.width, viewportSize.height);
CGPoint contentOffset = context.initialContentOffset;
CGRect initialRect = CGRectMake(contentOffset.x, contentOffset.y, viewportSize.width, viewportSize.height);
CGRect measureRect = CGRectExpandToRangeWithScrollableDirections(initialRect,
kASDefaultMeasureRangeTuningParameters,
context.scrollableDirections,
Expand Down
1 change: 1 addition & 0 deletions Source/Private/ASCollectionLayoutContext+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, weak, readonly) ASCollectionLayoutCache *layoutCache;

- (instancetype)initWithViewportSize:(CGSize)viewportSize
initialContentOffset:(CGPoint)initialContentOffset
scrollableDirections:(ASScrollDirection)scrollableDirections
elements:(ASElementMap *)elements
layoutDelegateClass:(Class<ASCollectionLayoutDelegate>)layoutDelegateClass
Expand Down
4 changes: 4 additions & 0 deletions Source/Private/ASCollectionView+Undeprecated.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ NS_ASSUME_NONNULL_BEGIN

@property (nonatomic, weak) id<ASCollectionViewLayoutInspecting> layoutInspector;

@property (nonatomic, assign) CGPoint contentOffset;

/**
* Tuning parameters for a range type in full mode.
*
Expand Down Expand Up @@ -292,6 +294,8 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (nullable NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode AS_WARN_UNUSED_RESULT;

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;

@end

NS_ASSUME_NONNULL_END
32 changes: 15 additions & 17 deletions Source/Private/ASTableView+Undeprecated.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ NS_ASSUME_NONNULL_BEGIN

@property (nonatomic, weak) id<ASTableDelegate> asyncDelegate;
@property (nonatomic, weak) id<ASTableDataSource> asyncDataSource;
@property (nonatomic, assign) CGPoint contentOffset;
@property (nonatomic, assign) BOOL automaticallyAdjustsContentOffset;
@property (nonatomic, assign) BOOL inverted;
@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForVisibleRows;
@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForSelectedRows;
@property (nonatomic, readonly, nullable) NSIndexPath *indexPathForSelectedRow;

/**
* The number of screens left to scroll before the delegate -tableView:beginBatchFetchingWithContext: is called.
*
* Defaults to two screenfuls.
*/
@property (nonatomic, assign) CGFloat leadingScreensForBatching;

/**
* Initializer.
Expand All @@ -44,10 +57,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style;

@property (nonatomic, assign) BOOL automaticallyAdjustsContentOffset;

@property (nonatomic, assign) BOOL inverted;

/**
* Tuning parameters for a range type in full mode.
*
Expand Down Expand Up @@ -109,12 +118,6 @@ NS_ASSUME_NONNULL_BEGIN

- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;

@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForVisibleRows;

@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForSelectedRows;

@property (nonatomic, readonly, nullable) NSIndexPath *indexPathForSelectedRow;

- (nullable NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point;

- (nullable NSArray<NSIndexPath *> *)indexPathsForRowsInRect:(CGRect)rect;
Expand All @@ -135,13 +138,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (nullable NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode AS_WARN_UNUSED_RESULT;

/**
* The number of screens left to scroll before the delegate -tableView:beginBatchFetchingWithContext: is called.
*
* Defaults to two screenfuls.
*/
@property (nonatomic, assign) CGFloat leadingScreensForBatching;

/**
* Reload everything from scratch, destroying the working range and all cached nodes.
*
Expand Down Expand Up @@ -311,5 +307,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;

@end
NS_ASSUME_NONNULL_END
Loading