Skip to content

Commit 48ba7fd

Browse files
committed
fix(ios): measure padded LiquidGlass content inside its padding
LiquidGlass and LiquidGlassContainer zeroed their padding and border while measuring (#11134), assuming the parent had already removed the child's padding from the measure spec. No layout does that, so padded content was measured at the full width and then offset by the padding in onLayout, overflowing and clipping. Measure through GridLayout/AbsoluteLayout as-is and keep the local-coordinate onLayout. Closes #11561
1 parent 3224f1b commit 48ba7fd

3 files changed

Lines changed: 47 additions & 76 deletions

File tree

‎apps/automated/src/ui/layouts/flexbox-layout-tests.ts‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1834,3 +1834,50 @@ export const testLiquidGlassViews_do_not_crash_when_updating_iosGlassEffect = is
18341834
TKUnit.assertTrue(root.isLoaded, 'Liquid glass view tree should remain loaded after glass effect updates.');
18351835
})
18361836
: undefined;
1837+
1838+
let getGlassViews = (template: string) => {
1839+
let root = Builder.parse(template);
1840+
1841+
return {
1842+
root,
1843+
parent: root.getViewById('parent') as View,
1844+
glass: root.getViewById('glass') as View,
1845+
child: root.getViewById('child') as View,
1846+
};
1847+
};
1848+
1849+
// #11134 assumed the parent removes the child's padding from the measure spec;
1850+
// no layout does that (issue #11561), so padded glass must measure its content
1851+
// inside the padding, not at the full border-box width.
1852+
1853+
let activity_liquidglass_padding = () =>
1854+
getGlassViews(
1855+
`<FlexboxLayout iosOverflowSafeArea="false" id="parent" width="300" height="300" flexDirection="${FlexDirection.ROW}" backgroundColor="gray">
1856+
<LiquidGlass id="glass" width="300" height="100" paddingLeft="20" paddingRight="20">
1857+
<Label id="child" text="content" horizontalAlignment="stretch" />
1858+
</LiquidGlass>
1859+
</FlexboxLayout>`,
1860+
);
1861+
1862+
export const testLiquidGlassFlexboxLayout_padding_measures_content_box = isIOS
1863+
? test(activity_liquidglass_padding, noop, ({ glass, child }) => {
1864+
closeEnough(width(child), dipToDp(260), `Expected ${child} width to equal glass width minus 2x20 padding`);
1865+
isLeftWith(glass, child, dipToDp(20), `Expected ${child} to start 20dip inside ${glass}`);
1866+
})
1867+
: undefined;
1868+
1869+
let activity_liquidglasscontainer_autowidth = () =>
1870+
getGlassViews(
1871+
`<FlexboxLayout iosOverflowSafeArea="false" id="parent" flexDirection="${FlexDirection.ROW}" alignItems="${AlignItems.FLEX_START}" backgroundColor="gray">
1872+
<LiquidGlassContainer id="glass" paddingLeft="20" paddingRight="20" paddingTop="10" paddingBottom="10">
1873+
<Label id="child" width="100" height="40" />
1874+
</LiquidGlassContainer>
1875+
</FlexboxLayout>`,
1876+
);
1877+
1878+
export const testLiquidGlassContainerFlexboxLayout_padding_wraps_content = isIOS
1879+
? test(activity_liquidglasscontainer_autowidth, noop, ({ glass }) => {
1880+
closeEnough(width(glass), dipToDp(140), `Expected ${glass} width to equal child width plus 2x20 padding`);
1881+
closeEnough(height(glass), dipToDp(60), `Expected ${glass} height to equal child height plus 2x10 padding`);
1882+
})
1883+
: undefined;

‎packages/core/ui/layouts/liquid-glass-container/index.ios.ts‎

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -55,44 +55,6 @@ export class LiquidGlassContainer extends LiquidGlassContainerCommon {
5555
return false;
5656
}
5757

58-
// When LiquidGlassContainer is a child of FlexboxLayout (or any layout that passes
59-
// a measure spec already reduced by the child's padding), AbsoluteLayout.onMeasure
60-
// would subtract our padding a second time. To prevent this double-deduction we
61-
// temporarily zero the effective padding/border values before delegating to the
62-
// AbsoluteLayout measurement, then restore them immediately after.
63-
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
64-
const pl = this.effectivePaddingLeft;
65-
const pr = this.effectivePaddingRight;
66-
const pt = this.effectivePaddingTop;
67-
const pb = this.effectivePaddingBottom;
68-
const bl = this.effectiveBorderLeftWidth;
69-
const br = this.effectiveBorderRightWidth;
70-
const bt = this.effectiveBorderTopWidth;
71-
const bb = this.effectiveBorderBottomWidth;
72-
73-
this.effectivePaddingLeft = 0;
74-
this.effectivePaddingRight = 0;
75-
this.effectivePaddingTop = 0;
76-
this.effectivePaddingBottom = 0;
77-
this.effectiveBorderLeftWidth = 0;
78-
this.effectiveBorderRightWidth = 0;
79-
this.effectiveBorderTopWidth = 0;
80-
this.effectiveBorderBottomWidth = 0;
81-
82-
try {
83-
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
84-
} finally {
85-
this.effectivePaddingLeft = pl;
86-
this.effectivePaddingRight = pr;
87-
this.effectivePaddingTop = pt;
88-
this.effectivePaddingBottom = pb;
89-
this.effectiveBorderLeftWidth = bl;
90-
this.effectiveBorderRightWidth = br;
91-
this.effectiveBorderTopWidth = bt;
92-
this.effectiveBorderBottomWidth = bb;
93-
}
94-
}
95-
9658
// When children animate with translate (layer transform), UIVisualEffectView-based
9759
// container effects may recompute based on the underlying frames (not transforms),
9860
// which can cause jumps. Normalize any residual translation into the

‎packages/core/ui/layouts/liquid-glass/index.ios.ts‎

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -48,44 +48,6 @@ export class LiquidGlass extends LiquidGlassCommon {
4848
return false;
4949
}
5050

51-
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
52-
// When LiquidGlass is a child of FlexboxLayout (or any layout that passes a child
53-
// measure spec already reduced by the child's padding), GridLayout.onMeasure would
54-
// subtract our padding a second time. To prevent this double-deduction we temporarily
55-
// zero the effective padding/border values before delegating to the GridLayout
56-
// measurement, then restore them immediately after.
57-
const pl = this.effectivePaddingLeft;
58-
const pr = this.effectivePaddingRight;
59-
const pt = this.effectivePaddingTop;
60-
const pb = this.effectivePaddingBottom;
61-
const bl = this.effectiveBorderLeftWidth;
62-
const br = this.effectiveBorderRightWidth;
63-
const bt = this.effectiveBorderTopWidth;
64-
const bb = this.effectiveBorderBottomWidth;
65-
66-
this.effectivePaddingLeft = 0;
67-
this.effectivePaddingRight = 0;
68-
this.effectivePaddingTop = 0;
69-
this.effectivePaddingBottom = 0;
70-
this.effectiveBorderLeftWidth = 0;
71-
this.effectiveBorderRightWidth = 0;
72-
this.effectiveBorderTopWidth = 0;
73-
this.effectiveBorderBottomWidth = 0;
74-
75-
try {
76-
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
77-
} finally {
78-
this.effectivePaddingLeft = pl;
79-
this.effectivePaddingRight = pr;
80-
this.effectivePaddingTop = pt;
81-
this.effectivePaddingBottom = pb;
82-
this.effectiveBorderLeftWidth = bl;
83-
this.effectiveBorderRightWidth = br;
84-
this.effectiveBorderTopWidth = bt;
85-
this.effectiveBorderBottomWidth = bb;
86-
}
87-
}
88-
8951
public onLayout(left: number, top: number, right: number, bottom: number): void {
9052
// GridLayout.onLayout computes column/row offsets relative to (left, top), then
9153
// adds its own padding on top. Since the FlexboxLayout (or parent) already placed

0 commit comments

Comments
 (0)