diff --git a/apps/app/ui-tests-app/flexbox/flexbox-4834.css b/apps/app/ui-tests-app/flexbox/flexbox-4834.css
new file mode 100644
index 000000000..f2714f66b
--- /dev/null
+++ b/apps/app/ui-tests-app/flexbox/flexbox-4834.css
@@ -0,0 +1,14 @@
+image {
+ width: 40;
+ height: 40;
+ flex-grow: 0;
+ flex-shrink: 0;
+}
+
+Label {
+ border-width: 1;
+ border-color: black;
+ padding: 0;
+ flex-grow: 1;
+ flex-shrink: 1;
+}
diff --git a/apps/app/ui-tests-app/flexbox/flexbox-4834.xml b/apps/app/ui-tests-app/flexbox/flexbox-4834.xml
new file mode 100644
index 000000000..ac96bd2b8
--- /dev/null
+++ b/apps/app/ui-tests-app/flexbox/flexbox-4834.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/app/ui-tests-app/flexbox/flexbox-main-page.ts b/apps/app/ui-tests-app/flexbox/flexbox-main-page.ts
index f1773098d..b7a852153 100644
--- a/apps/app/ui-tests-app/flexbox/flexbox-main-page.ts
+++ b/apps/app/ui-tests-app/flexbox/flexbox-main-page.ts
@@ -17,6 +17,7 @@ export function loadExamples() {
examples.set("flexrepeat", "flexbox/flexbox-repeater");
examples.set("flex-perf", "flexbox/flexbox-perf-comparison");
examples.set("flexbox-4143", "flexbox/flexbox-4143");
+ examples.set("flexbox-4834", "flexbox/flexbox-4834");
return examples;
}
\ No newline at end of file
diff --git a/tns-core-modules/ui/label/label.ios.ts b/tns-core-modules/ui/label/label.ios.ts
index 7d00a2bb5..e35c13297 100644
--- a/tns-core-modules/ui/label/label.ios.ts
+++ b/tns-core-modules/ui/label/label.ios.ts
@@ -68,7 +68,11 @@ export class Label extends TextBase implements LabelDefinition {
this._fixedSize = (widthMode === layout.EXACTLY ? FixedSize.WIDTH : FixedSize.NONE)
| (heightMode === layout.EXACTLY ? FixedSize.HEIGHT : FixedSize.NONE);
- const nativeSize = layout.measureNativeView(nativeView, width, widthMode, height, heightMode);
+ // NOTE: utils.measureNativeView(...) relies on UIView.sizeThatFits(...) that
+ // seems to have various issues when laying out UILabel instances.
+ // We use custom measure logic here that relies on overriden
+ // UILabel.textRectForBounds:limitedToNumberOfLines: in TNSLabel widget.
+ const nativeSize = this._measureNativeView(width, widthMode, height, heightMode);
let labelWidth = nativeSize.width;
if (this.textWrap && widthMode === layout.AT_MOST) {
@@ -85,6 +89,22 @@ export class Label extends TextBase implements LabelDefinition {
}
}
+ private _measureNativeView(width: number, widthMode: number, height: number, heightMode: number): { width: number, height: number } {
+ const view = this.nativeViewProtected;
+
+ const nativeSize = view.textRectForBoundsLimitedToNumberOfLines(
+ CGRectMake(
+ 0,
+ 0,
+ widthMode === 0 /* layout.UNSPECIFIED */ ? Number.POSITIVE_INFINITY : layout.toDeviceIndependentPixels(width),
+ heightMode === 0 /* layout.UNSPECIFIED */ ? Number.POSITIVE_INFINITY : layout.toDeviceIndependentPixels(height)
+ ), 0).size;
+
+ nativeSize.width = layout.round(layout.toDevicePixels(nativeSize.width));
+ nativeSize.height = layout.round(layout.toDevicePixels(nativeSize.height));
+ return nativeSize;
+ }
+
[whiteSpaceProperty.setNative](value: WhiteSpace) {
const nativeView = this.nativeViewProtected;
switch (value) {
diff --git a/tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.ios.ts b/tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.ios.ts
index ee28c43d7..89021c4de 100644
--- a/tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.ios.ts
+++ b/tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.ios.ts
@@ -595,8 +595,25 @@ export class FlexboxLayout extends FlexboxLayoutBase {
} else {
accumulatedRoundError = rawCalculatedWidth - roundedCalculatedWidth;
}
- child.measure(makeMeasureSpec(roundedCalculatedWidth, EXACTLY), makeMeasureSpec(child.getMeasuredHeight(), EXACTLY));
+
+ const childWidthMeasureSpec = makeMeasureSpec(roundedCalculatedWidth, EXACTLY);
+
+ // NOTE: for controls that support internal content wrapping (e.g. UILabel) reducing the width
+ // might result in increased height e.g. text that could be shown on one line for larger
+ // width needs to be wrapped in two when width is reduced.
+ // As a result we cannot unconditionally measure with EXACTLY the current measured height
+ const childHeightMeasureSpec = FlexboxLayout.getChildMeasureSpec(this._currentHeightMeasureSpec,
+ lp.effectivePaddingTop + lp.effectivePaddingBottom + lp.effectiveMarginTop
+ + lp.effectiveMarginBottom, lp.effectiveHeight < 0 ? WRAP_CONTENT : lp.effectiveHeight);
+
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
child.effectiveMinWidth = minWidth;
+
+ // make sure crossSize is up-to-date as child calculated height might have increased
+ flexLine._crossSize = Math.max(
+ flexLine._crossSize,
+ child.getMeasuredHeight() + lp.effectiveMarginTop + lp.effectiveMarginBottom
+ );
}
flexLine._mainSize += child.getMeasuredWidth() + lp.effectiveMarginLeft + lp.effectiveMarginRight;
} else {