diff --git a/YogaKit/Source/YGLayout.m b/YogaKit/Source/YGLayout.m index 836b34a5..7779c437 100644 --- a/YogaKit/Source/YGLayout.m +++ b/YogaKit/Source/YGLayout.m @@ -129,6 +129,7 @@ static YGConfigRef globalConfig; @interface YGLayout () @property (nonatomic, weak, readonly) UIView *view; +@property(nonatomic, assign, readonly) BOOL isUIView; @end @@ -153,6 +154,7 @@ static YGConfigRef globalConfig; YGNodeSetContext(_node, (__bridge void *) view); _isEnabled = NO; _isIncludedInLayout = YES; + _isUIView = [view isMemberOfClass:[UIView class]]; } return self; @@ -331,10 +333,20 @@ static YGSize YGMeasureView( const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height; UIView *view = (__bridge UIView*) YGNodeGetContext(node); - const CGSize sizeThatFits = [view sizeThatFits:(CGSize) { - .width = constrainedWidth, - .height = constrainedHeight, - }]; + CGSize sizeThatFits = CGSizeZero; + + // The default implementation of sizeThatFits: returns the existing size of + // the view. That means that if we want to layout an empty UIView, which + // already has got a frame set, its measured size should be CGSizeZero, but + // UIKit returns the existing size. + // + // See https://github.com/facebook/yoga/issues/606 for more information. + if (!view.yoga.isUIView || [view.subviews count] > 0) { + sizeThatFits = [view sizeThatFits:(CGSize){ + .width = constrainedWidth, + .height = constrainedHeight, + }]; + } return (YGSize) { .width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode), diff --git a/YogaKit/Tests/YogaKitTests.m b/YogaKit/Tests/YogaKitTests.m index 945d4d24..b9d3a6ed 100644 --- a/YogaKit/Tests/YogaKitTests.m +++ b/YogaKit/Tests/YogaKitTests.m @@ -127,6 +127,15 @@ XCTAssertEqual(longTextLabelSize.width + textBadgeView.yoga.intrinsicSize.width, containerSize.width); } +- (void)testSizeThatFitsEmptyView { + UIView* view = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 200, 200)]; + view.yoga.isEnabled = YES; + + const CGSize viewSize = view.yoga.intrinsicSize; + XCTAssertEqual(viewSize.height, 0); + XCTAssertEqual(viewSize.width, 0); +} + - (void)testPreservingOrigin { UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,75)];