Use bounds and position to layout subnodes, instead of frame because it is not safe in case the transform property constains a non-identity transform.

This commit is contained in:
Huy Nguyen 2015-10-07 21:46:07 +03:00
parent 697142240c
commit 5a2fea7c1d
3 changed files with 30 additions and 20 deletions

View File

@ -744,6 +744,26 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
} }
} }
- (void)__setSafeFrame:(CGRect)rect
{
BOOL useLayer = (_layer && ASDisplayNodeThreadIsMain());
CGPoint origin = (useLayer ? _layer.bounds.origin : self.bounds.origin);
CGPoint anchorPoint = (useLayer ? _layer.anchorPoint : self.anchorPoint);
CGRect bounds = (CGRect){ origin, rect.size };
CGPoint position = CGPointMake(rect.origin.x + rect.size.width * anchorPoint.x,
rect.origin.y + rect.size.height * anchorPoint.y);
if (useLayer) {
_layer.bounds = bounds;
_layer.position = position;
} else {
self.bounds = bounds;
self.position = position;
}
}
// These private methods ensure that subclasses are not required to call super in order for _renderingSubnodes to be properly managed. // These private methods ensure that subclasses are not required to call super in order for _renderingSubnodes to be properly managed.
- (void)__layout - (void)__layout
@ -1691,10 +1711,10 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
// Assume that _layout was flattened and is 1-level deep. // Assume that _layout was flattened and is 1-level deep.
for (ASLayout *subnodeLayout in _layout.sublayouts) { for (ASLayout *subnodeLayout in _layout.sublayouts) {
ASDisplayNodeAssert([_subnodes containsObject:subnodeLayout.layoutableObject], @"Cached sublayouts must only contain subnodes' layout."); ASDisplayNodeAssert([_subnodes containsObject:subnodeLayout.layoutableObject], @"Cached sublayouts must only contain subnodes' layout.");
((ASDisplayNode *)subnodeLayout.layoutableObject).frame = CGRectMake(subnodeLayout.position.x, [((ASDisplayNode *)subnodeLayout.layoutableObject) __setSafeFrame:CGRectMake(subnodeLayout.position.x,
subnodeLayout.position.y, subnodeLayout.position.y,
subnodeLayout.size.width, subnodeLayout.size.width,
subnodeLayout.size.height); subnodeLayout.size.height)];
} }
} }

View File

@ -143,22 +143,7 @@
ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode setFrame:] - self.transform must be identity in order to set the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)"); ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode setFrame:] - self.transform must be identity in order to set the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)");
#endif #endif
BOOL useLayer = (_layer && ASDisplayNodeThreadIsMain()); [self __setSafeFrame:rect];
CGPoint origin = (useLayer ? _layer.bounds.origin : self.bounds.origin);
CGPoint anchorPoint = (useLayer ? _layer.anchorPoint : self.anchorPoint);
CGRect bounds = (CGRect){ origin, rect.size };
CGPoint position = CGPointMake(rect.origin.x + rect.size.width * anchorPoint.x,
rect.origin.y + rect.size.height * anchorPoint.y);
if (useLayer) {
_layer.bounds = bounds;
_layer.position = position;
} else {
self.bounds = bounds;
self.position = position;
}
} }
- (void)setNeedsDisplay - (void)setNeedsDisplay

View File

@ -126,6 +126,11 @@ typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides) {
- (ASLayout *)__measureWithSizeRange:(ASSizeRange)constrainedSize; - (ASLayout *)__measureWithSizeRange:(ASSizeRange)constrainedSize;
- (void)__setNeedsLayout; - (void)__setNeedsLayout;
/**
* Sets a new frame to this node by changing its bounds and position. This method can be safely called even if the transform property
* contains a non-identity transform, because bounds and position can be changed in such case.
*/
- (void)__setSafeFrame:(CGRect)rect;
- (void)__layout; - (void)__layout;
- (void)__setSupernode:(ASDisplayNode *)supernode; - (void)__setSupernode:(ASDisplayNode *)supernode;