mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-15 16:36:36 +00:00
Allow layouts to be accessible in context
This commit is contained in:
parent
6aae68ead4
commit
6f37bb40d9
@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
#import <AsyncDisplayKit/ASDisplayNode.h>
|
#import <AsyncDisplayKit/ASDisplayNode.h>
|
||||||
|
|
||||||
|
extern NSString * const ASTransitionContextFromLayoutKey;
|
||||||
|
extern NSString * const ASTransitionContextToLayoutKey;
|
||||||
|
|
||||||
@protocol ASContextTransitioning <NSObject>
|
@protocol ASContextTransitioning <NSObject>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,19 +19,19 @@
|
|||||||
- (BOOL)isAnimated;
|
- (BOOL)isAnimated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract The destination layout being transitioned to
|
* @abstract Retrieve either the "from" or "to" layout
|
||||||
*/
|
*/
|
||||||
- (ASLayout *)layout;
|
- (ASLayout *)layoutForKey:(NSString *)key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstrat The destination constrainedSize being transitioned to
|
* @abstract Retrieve either the "from" or "to" constrainedSize
|
||||||
*/
|
*/
|
||||||
- (ASSizeRange)constrainedSize;
|
- (ASSizeRange)constrainedSizeForKey:(NSString *)key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract Subnodes in the new layout
|
* @abstract Retrieve the subnodes from either the "from" or "to" layout
|
||||||
*/
|
*/
|
||||||
- (NSArray<ASDisplayNode *> *)subnodes;
|
- (NSArray<ASDisplayNode *> *)subnodesForKey:(NSString *)key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract Subnodes that have been inserted in the layout transition
|
* @abstract Subnodes that have been inserted in the layout transition
|
||||||
|
@ -610,34 +610,43 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
|
|
||||||
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
|
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
|
||||||
{
|
{
|
||||||
return [self measureWithSizeRange:constrainedSize completion:^(ASLayout *pendingLayout, ASSizeRange constrainedSize) {
|
return [self measureWithSizeRange:constrainedSize completion:^{
|
||||||
if ([[self class] usesImplicitHierarchyManagement]) {
|
if ([[self class] usesImplicitHierarchyManagement]) {
|
||||||
[self __implicitlyInsertSubnodes];
|
[self __implicitlyInsertSubnodes];
|
||||||
[self __implicitlyRemoveSubnodes];
|
[self __implicitlyRemoveSubnodes];
|
||||||
}
|
}
|
||||||
[self __applyLayout:pendingLayout constrainedSize:constrainedSize];
|
[self __completeLayoutCalculation];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize completion:(void(^)(ASLayout *, ASSizeRange))completion
|
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize completion:(void(^)())completion
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertThreadAffinity(self);
|
ASDisplayNodeAssertThreadAffinity(self);
|
||||||
ASDN::MutexLocker l(_propertyLock);
|
ASDN::MutexLocker l(_propertyLock);
|
||||||
if (![self __shouldSize])
|
if (![self __shouldSize])
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
ASLayout *pendingLayout = _layout;
|
|
||||||
|
|
||||||
// only calculate the size if
|
// only calculate the size if
|
||||||
// - we haven't already
|
// - we haven't already
|
||||||
// - the constrained size range is different
|
// - the constrained size range is different
|
||||||
if (!_flags.isMeasured || !ASSizeRangeEqualToSizeRange(constrainedSize, _constrainedSize)) {
|
if (!_flags.isMeasured || !ASSizeRangeEqualToSizeRange(constrainedSize, _constrainedSize)) {
|
||||||
pendingLayout = [self calculateLayoutThatFits:constrainedSize];
|
_previousLayout = _layout;
|
||||||
[self __calculateSubnodeOperationsWithPendingLayout:pendingLayout currentLayout:_layout];
|
_layout = [self calculateLayoutThatFits:constrainedSize];
|
||||||
completion(pendingLayout, constrainedSize);
|
|
||||||
|
ASDisplayNodeAssertTrue(_layout.layoutableObject == self);
|
||||||
|
ASDisplayNodeAssertTrue(_layout.size.width >= 0.0);
|
||||||
|
ASDisplayNodeAssertTrue(_layout.size.height >= 0.0);
|
||||||
|
|
||||||
|
_previousConstrainedSize = _constrainedSize;
|
||||||
|
_constrainedSize = constrainedSize;
|
||||||
|
|
||||||
|
[self __calculateSubnodeOperationsWithLayout:_layout previousLayout:_previousLayout];
|
||||||
|
_flags.isMeasured = YES;
|
||||||
|
|
||||||
|
completion();
|
||||||
}
|
}
|
||||||
|
|
||||||
return pendingLayout;
|
return _layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASLayout *)transitionLayoutWithAnimation:(BOOL)animated
|
- (ASLayout *)transitionLayoutWithAnimation:(BOOL)animated
|
||||||
@ -648,50 +657,41 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
|
|
||||||
- (ASLayout *)transitionLayoutWithSizeRange:(ASSizeRange)constrainedSize animated:(BOOL)animated
|
- (ASLayout *)transitionLayoutWithSizeRange:(ASSizeRange)constrainedSize animated:(BOOL)animated
|
||||||
{
|
{
|
||||||
return [self measureWithSizeRange:constrainedSize completion:^(ASLayout *pendingLayout, ASSizeRange constrainedSize) {
|
return [self measureWithSizeRange:constrainedSize completion:^{
|
||||||
_transitionContext = [[_ASTransitionContext alloc] initWithLayout:pendingLayout
|
_transitionContext = [[_ASTransitionContext alloc] initWithAnimation:animated delegate:self];
|
||||||
constrainedSize:constrainedSize
|
|
||||||
animated:animated
|
|
||||||
delegate:self];
|
|
||||||
[self __implicitlyInsertSubnodes];
|
[self __implicitlyInsertSubnodes];
|
||||||
[self animateLayoutTransition:_transitionContext];
|
[self animateLayoutTransition:_transitionContext];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)__calculateSubnodeOperationsWithPendingLayout:(ASLayout *)pendingLayout currentLayout:(ASLayout *)currentLayout
|
- (void)__calculateSubnodeOperationsWithLayout:(ASLayout *)layout previousLayout:(ASLayout *)previousLayout
|
||||||
{
|
{
|
||||||
if (_layout) {
|
if (previousLayout) {
|
||||||
NSIndexSet *insertions, *deletions;
|
NSIndexSet *insertions, *deletions;
|
||||||
[currentLayout.immediateSublayouts asdk_diffWithArray:pendingLayout.immediateSublayouts
|
[previousLayout.immediateSublayouts asdk_diffWithArray:layout.immediateSublayouts
|
||||||
insertions:&insertions
|
insertions:&insertions
|
||||||
deletions:&deletions
|
deletions:&deletions
|
||||||
compareBlock:^BOOL(ASLayout *lhs, ASLayout *rhs) {
|
compareBlock:^BOOL(ASLayout *lhs, ASLayout *rhs) {
|
||||||
return ASObjectIsEqual(lhs.layoutableObject, rhs.layoutableObject);
|
return ASObjectIsEqual(lhs.layoutableObject, rhs.layoutableObject);
|
||||||
}];
|
}];
|
||||||
filterNodesInLayoutAtIndexes(pendingLayout, insertions, &_insertedSubnodes, &_insertedSubnodePositions);
|
filterNodesInLayoutAtIndexes(layout, insertions, &_insertedSubnodes, &_insertedSubnodePositions);
|
||||||
filterNodesInLayoutAtIndexesWithIntersectingNodes(currentLayout,
|
filterNodesInLayoutAtIndexesWithIntersectingNodes(previousLayout,
|
||||||
deletions,
|
deletions,
|
||||||
_insertedSubnodes,
|
_insertedSubnodes,
|
||||||
&_removedSubnodes,
|
&_removedSubnodes,
|
||||||
&_removedSubnodePositions);
|
&_removedSubnodePositions);
|
||||||
} else {
|
} else {
|
||||||
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [pendingLayout.immediateSublayouts count])];
|
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [layout.immediateSublayouts count])];
|
||||||
filterNodesInLayoutAtIndexes(pendingLayout, indexes, &_insertedSubnodes, &_insertedSubnodePositions);
|
filterNodesInLayoutAtIndexes(layout, indexes, &_insertedSubnodes, &_insertedSubnodePositions);
|
||||||
_removedSubnodes = nil;
|
_removedSubnodes = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)__applyLayout:(ASLayout *)layout constrainedSize:(ASSizeRange)constrainedSize
|
- (void)__completeLayoutCalculation
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertTrue(layout.layoutableObject == self);
|
|
||||||
ASDisplayNodeAssertTrue(layout.size.width >= 0.0);
|
|
||||||
ASDisplayNodeAssertTrue(layout.size.height >= 0.0);
|
|
||||||
|
|
||||||
_layout = layout;
|
|
||||||
_constrainedSize = constrainedSize;
|
|
||||||
_flags.isMeasured = YES;
|
|
||||||
_insertedSubnodes = nil;
|
_insertedSubnodes = nil;
|
||||||
_removedSubnodes = nil;
|
_removedSubnodes = nil;
|
||||||
|
_previousLayout = nil;
|
||||||
[self calculatedLayoutDidChange];
|
[self calculatedLayoutDidChange];
|
||||||
|
|
||||||
// we generate placeholders at measureWithSizeRange: time so that a node is guaranteed
|
// we generate placeholders at measureWithSizeRange: time so that a node is guaranteed
|
||||||
@ -777,7 +777,7 @@ static inline void filterNodesInLayoutAtIndexesWithIntersectingNodes(
|
|||||||
- (void)didCompleteTransitionLayout:(id<ASContextTransitioning>)context
|
- (void)didCompleteTransitionLayout:(id<ASContextTransitioning>)context
|
||||||
{
|
{
|
||||||
[self __implicitlyRemoveSubnodes];
|
[self __implicitlyRemoveSubnodes];
|
||||||
[self __applyLayout:context.layout constrainedSize:context.constrainedSize];
|
[self __completeLayoutCalculation];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Implicit node hierarchy managagment
|
#pragma mark - Implicit node hierarchy managagment
|
||||||
@ -814,6 +814,27 @@ static inline void filterNodesInLayoutAtIndexesWithIntersectingNodes(
|
|||||||
return _removedSubnodes;
|
return _removedSubnodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (ASLayout *)transitionContext:(_ASTransitionContext *)context layoutForKey:(NSString *)key
|
||||||
|
{
|
||||||
|
if ([key isEqualToString:ASTransitionContextFromLayoutKey]) {
|
||||||
|
return _previousLayout;
|
||||||
|
} else if ([key isEqualToString:ASTransitionContextToLayoutKey]) {
|
||||||
|
return _layout;
|
||||||
|
} else {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (ASSizeRange)transitionContext:(_ASTransitionContext *)context constrainedSizeForKey:(NSString *)key
|
||||||
|
{
|
||||||
|
if ([key isEqualToString:ASTransitionContextFromLayoutKey]) {
|
||||||
|
return _previousConstrainedSize;
|
||||||
|
} else if ([key isEqualToString:ASTransitionContextToLayoutKey]) {
|
||||||
|
return _constrainedSize;
|
||||||
|
} else {
|
||||||
|
return ASSizeRangeMake(CGSizeZero, CGSizeZero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)transitionContext:(_ASTransitionContext *)context didComplete:(BOOL)didComplete
|
- (void)transitionContext:(_ASTransitionContext *)context didComplete:(BOOL)didComplete
|
||||||
{
|
{
|
||||||
[self didCompleteTransitionLayout:context];
|
[self didCompleteTransitionLayout:context];
|
||||||
|
@ -62,8 +62,12 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
|
|||||||
// This is the desired contentsScale, not the scale at which the layer's contents should be displayed
|
// This is the desired contentsScale, not the scale at which the layer's contents should be displayed
|
||||||
CGFloat _contentsScaleForDisplay;
|
CGFloat _contentsScaleForDisplay;
|
||||||
|
|
||||||
|
ASLayout *_previousLayout;
|
||||||
ASLayout *_layout;
|
ASLayout *_layout;
|
||||||
|
|
||||||
|
ASSizeRange _previousConstrainedSize;
|
||||||
ASSizeRange _constrainedSize;
|
ASSizeRange _constrainedSize;
|
||||||
|
|
||||||
UIEdgeInsets _hitTestSlop;
|
UIEdgeInsets _hitTestSlop;
|
||||||
NSMutableArray *_subnodes;
|
NSMutableArray *_subnodes;
|
||||||
|
|
||||||
|
@ -16,9 +16,13 @@
|
|||||||
@protocol _ASTransitionContextDelegate <NSObject>
|
@protocol _ASTransitionContextDelegate <NSObject>
|
||||||
|
|
||||||
- (NSArray<ASDisplayNode *> *)currentSubnodesWithTransitionContext:(_ASTransitionContext *)context;
|
- (NSArray<ASDisplayNode *> *)currentSubnodesWithTransitionContext:(_ASTransitionContext *)context;
|
||||||
|
|
||||||
- (NSArray<ASDisplayNode *> *)insertedSubnodesWithTransitionContext:(_ASTransitionContext *)context;
|
- (NSArray<ASDisplayNode *> *)insertedSubnodesWithTransitionContext:(_ASTransitionContext *)context;
|
||||||
- (NSArray<ASDisplayNode *> *)removedSubnodesWithTransitionContext:(_ASTransitionContext *)context;
|
- (NSArray<ASDisplayNode *> *)removedSubnodesWithTransitionContext:(_ASTransitionContext *)context;
|
||||||
|
|
||||||
|
- (ASLayout *)transitionContext:(_ASTransitionContext *)context layoutForKey:(NSString *)key;
|
||||||
|
- (ASSizeRange)transitionContext:(_ASTransitionContext *)context constrainedSizeForKey:(NSString *)key;
|
||||||
|
|
||||||
- (void)transitionContext:(_ASTransitionContext *)context didComplete:(BOOL)didComplete;
|
- (void)transitionContext:(_ASTransitionContext *)context didComplete:(BOOL)didComplete;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@ -27,10 +31,6 @@
|
|||||||
|
|
||||||
@property (assign, readonly, nonatomic, getter=isAnimated) BOOL animated;
|
@property (assign, readonly, nonatomic, getter=isAnimated) BOOL animated;
|
||||||
|
|
||||||
@property (strong, readonly) ASLayout *layout;
|
- (instancetype)initWithAnimation:(BOOL)animated delegate:(id<_ASTransitionContextDelegate>)delegate;
|
||||||
|
|
||||||
@property (assign, readonly) ASSizeRange constrainedSize;
|
|
||||||
|
|
||||||
- (instancetype)initWithLayout:(ASLayout *)layout constrainedSize:(ASSizeRange)constrainedSize animated:(BOOL)animated delegate:(id<_ASTransitionContextDelegate>)delegate;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -10,6 +10,10 @@
|
|||||||
|
|
||||||
#import "ASLayout.h"
|
#import "ASLayout.h"
|
||||||
|
|
||||||
|
|
||||||
|
NSString * const ASTransitionContextFromLayoutKey = @"org.asyncdisplaykit.ASTransitionContextFromLayoutKey";
|
||||||
|
NSString * const ASTransitionContextToLayoutKey = @"org.asyncdisplaykit.ASTransitionContextToLayoutKey";
|
||||||
|
|
||||||
@interface _ASTransitionContext ()
|
@interface _ASTransitionContext ()
|
||||||
|
|
||||||
@property (weak, nonatomic) id<_ASTransitionContextDelegate> delegate;
|
@property (weak, nonatomic) id<_ASTransitionContextDelegate> delegate;
|
||||||
@ -18,12 +22,10 @@
|
|||||||
|
|
||||||
@implementation _ASTransitionContext
|
@implementation _ASTransitionContext
|
||||||
|
|
||||||
- (instancetype)initWithLayout:(ASLayout *)layout constrainedSize:(ASSizeRange)constrainedSize animated:(BOOL)animated delegate:(id<_ASTransitionContextDelegate>)delegate
|
- (instancetype)initWithAnimation:(BOOL)animated delegate:(id<_ASTransitionContextDelegate>)delegate
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self) {
|
if (self) {
|
||||||
_layout = layout;
|
|
||||||
_constrainedSize = constrainedSize;
|
|
||||||
_animated = animated;
|
_animated = animated;
|
||||||
_delegate = delegate;
|
_delegate = delegate;
|
||||||
}
|
}
|
||||||
@ -32,6 +34,16 @@
|
|||||||
|
|
||||||
#pragma mark - ASContextTransitioning Protocol Implementation
|
#pragma mark - ASContextTransitioning Protocol Implementation
|
||||||
|
|
||||||
|
- (ASLayout *)layoutForKey:(NSString *)key
|
||||||
|
{
|
||||||
|
return [_delegate transitionContext:self layoutForKey:key];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASSizeRange)constrainedSizeForKey:(NSString *)key
|
||||||
|
{
|
||||||
|
return [_delegate transitionContext:self constrainedSizeForKey:key];
|
||||||
|
}
|
||||||
|
|
||||||
- (CGRect)initialFrameForNode:(ASDisplayNode *)node
|
- (CGRect)initialFrameForNode:(ASDisplayNode *)node
|
||||||
{
|
{
|
||||||
for (ASDisplayNode *subnode in [_delegate currentSubnodesWithTransitionContext:self]) {
|
for (ASDisplayNode *subnode in [_delegate currentSubnodesWithTransitionContext:self]) {
|
||||||
@ -44,7 +56,7 @@
|
|||||||
|
|
||||||
- (CGRect)finalFrameForNode:(ASDisplayNode *)node
|
- (CGRect)finalFrameForNode:(ASDisplayNode *)node
|
||||||
{
|
{
|
||||||
for (ASLayout *layout in _layout.sublayouts) {
|
for (ASLayout *layout in [self layoutForKey:ASTransitionContextToLayoutKey].sublayouts) {
|
||||||
if (layout.layoutableObject == node) {
|
if (layout.layoutableObject == node) {
|
||||||
return [layout frame];
|
return [layout frame];
|
||||||
}
|
}
|
||||||
@ -52,10 +64,10 @@
|
|||||||
return CGRectZero;
|
return CGRectZero;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<ASDisplayNode *> *)subnodes
|
- (NSArray<ASDisplayNode *> *)subnodesForKey:(NSString *)key
|
||||||
{
|
{
|
||||||
NSMutableArray<ASDisplayNode *> *subnodes = [NSMutableArray array];
|
NSMutableArray<ASDisplayNode *> *subnodes = [NSMutableArray array];
|
||||||
for (ASLayout *sublayout in _layout.immediateSublayouts) {
|
for (ASLayout *sublayout in [self layoutForKey:key].immediateSublayouts) {
|
||||||
[subnodes addObject:(ASDisplayNode *)sublayout.layoutableObject];
|
[subnodes addObject:(ASDisplayNode *)sublayout.layoutableObject];
|
||||||
}
|
}
|
||||||
return subnodes;
|
return subnodes;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user