[Layout] Automatic measurement on layout fixes (#2206)

* Don't measure range managed nodes automatically in the layout pass

* Fix auto measure a node mid transition
This commit is contained in:
Michael Schneider 2016-09-07 21:46:05 +02:00 committed by Adlai Holler
parent 8897614f0e
commit 0aeefaf25f
3 changed files with 13 additions and 27 deletions

View File

@ -1382,17 +1382,28 @@ ASLayoutableSizeHelperForwarding
- (void)measureNodeWithBoundsIfNecessary:(CGRect)bounds
{
BOOL supportsRangeManagedInterfaceState = NO;
BOOL hasDirtyLayout = NO;
CGSize calculatedLayoutSize = CGSizeZero;
{
ASDN::MutexLocker l(__instanceLock__);
supportsRangeManagedInterfaceState = [self supportsRangeManagedInterfaceState];
hasDirtyLayout = _calculatedDisplayNodeLayout->isDirty();
calculatedLayoutSize = _calculatedDisplayNodeLayout->layout.size;
}
// Check if it's a subnode in a layout transition. In this case no measurement is needed as it's part of
// the layout transition
if (ASHierarchyStateIncludesLayoutPending(_hierarchyState)) {
ASLayoutableContext context = ASLayoutableGetCurrentContext();
if (ASLayoutableContextIsNull(context) || _pendingTransitionID != context.transitionID) {
return;
}
}
// If no measure pass happened or the bounds changed between layout passes we manually trigger a measurement pass
// for the node using a size range equal to whatever bounds were provided to the node
if (hasDirtyLayout || CGSizeEqualToSize(calculatedLayoutSize, bounds.size) == NO) {
if (supportsRangeManagedInterfaceState == NO && (hasDirtyLayout || CGSizeEqualToSize(calculatedLayoutSize, bounds.size) == NO)) {
if (CGRectEqualToRect(bounds, CGRectZero)) {
LOG(@"Warning: No size given for node before node was trying to layout itself: %@. Please provide a frame for the node.", self);
} else {

View File

@ -44,31 +44,6 @@
ASXCTAssertEqualSizes(buttonNode.calculatedSize, nodeSize, @"Automatic measurement pass should have happened in layout pass");
}
- (void)testMeasureOnLayoutIfNotHappenedBeforeForRangeManagedNodes
{
CGSize nodeSize = CGSizeMake(100, 100);
ASDisplayNode *displayNode = [ASDisplayNode new];
[displayNode setSizeWithCGSize:nodeSize];
ASButtonNode *buttonNode = [ASButtonNode new];
[displayNode addSubnode:buttonNode];
[displayNode enterHierarchyState:ASHierarchyStateRangeManaged];
displayNode.frame = {.size = nodeSize};
buttonNode.frame = {.size = nodeSize};
ASXCTAssertEqualSizes(displayNode.calculatedSize, CGSizeZero, @"Calculated size before measurement and layout should be 0");
ASXCTAssertEqualSizes(buttonNode.calculatedSize, CGSizeZero, @"Calculated size before measurement and layout should be 0");
// Trigger layout pass without a maeasurment pass before
[displayNode.view layoutIfNeeded];
ASXCTAssertEqualSizes(displayNode.calculatedSize, nodeSize, @"Automatic measurement pass should have happened in layout pass");
ASXCTAssertEqualSizes(buttonNode.calculatedSize, nodeSize, @"Automatic measurement pass should have happened in layout pass");
}
#if DEBUG
- (void)testNotAllowAddingSubnodesInLayoutSpecThatFits
{

View File

@ -1988,7 +1988,7 @@ static bool stringContainsPointer(NSString *description, id p) {
// FIXME
// Supernode is measured, subnode isnt, transition starts, UIKit does a layout pass before measurement finishes
- (void)DISABLED_testThatItsSafeToAutomeasureANodeMidTransition
- (void)testThatItsSafeToAutomeasureANodeMidTransition
{
ASDisplayNode *supernode = [[ASDisplayNode alloc] init];
[supernode layoutThatFits:ASSizeRangeMake(CGSizeZero, CGSizeMake(100, 100))];