Skip to content

Commit 261b357

Browse files
fix-35615: Made code changes to fix Editor height ignoring HeightRequest when VerticalTextAlignment is Center or End under infinite height constraints on iOS and macOS.
1 parent abf0a5f commit 261b357

2 files changed

Lines changed: 55 additions & 11 deletions

File tree

src/Controls/tests/DeviceTests/Elements/Editor/EditorTests.iOS.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,45 @@ Task<bool> GetPlatformIsVisible(EditorHandler editorHandler)
6464
});
6565
}
6666

67+
[Theory]
68+
[InlineData(TextAlignment.Start, TextAlignment.Start)]
69+
[InlineData(TextAlignment.Center, TextAlignment.Start)]
70+
[InlineData(TextAlignment.End, TextAlignment.Start)]
71+
[InlineData(TextAlignment.Start, TextAlignment.Center)]
72+
[InlineData(TextAlignment.Center, TextAlignment.Center)]
73+
[InlineData(TextAlignment.End, TextAlignment.Center)]
74+
[InlineData(TextAlignment.Start, TextAlignment.End)]
75+
[InlineData(TextAlignment.Center, TextAlignment.End)]
76+
[InlineData(TextAlignment.End, TextAlignment.End)]
77+
[Description("Editor height should honour HeightRequest for all text alignment combinations when placed in an infinite height constraint layout.")]
78+
public async Task EditorHeightIsConsistentAcrossAllTextAlignments(TextAlignment horizontal, TextAlignment vertical)
79+
{
80+
SetupBuilder();
81+
82+
const double heightRequest = 100;
83+
84+
var editor = new Editor
85+
{
86+
Text = "testing",
87+
HeightRequest = heightRequest,
88+
HorizontalTextAlignment = horizontal,
89+
VerticalTextAlignment = vertical,
90+
};
91+
92+
var layout = new VerticalStackLayout
93+
{
94+
Children = { editor }
95+
};
96+
97+
await AttachAndRun<LayoutHandler>(layout, async (_) =>
98+
{
99+
var frame = editor.Frame;
100+
await WaitForUIUpdate(frame, editor);
101+
102+
Assert.Equal(heightRequest, editor.Height, tolerance: 1.0);
103+
});
104+
}
105+
67106
[Fact]
68107
[Description("Editor with AutoSize=TextChanges should continue to grow after a simulated rotation (width constraint change)")]
69108
public async Task AutoSizeTextChangesEditorGrowsAfterRotation()

src/Core/src/Handlers/Editor/EditorHandler.iOS.cs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ public override bool NeedsContainer
5555

5656
public override Size GetDesiredSize(double widthConstraint, double heightConstraint)
5757
{
58+
// When the height constraint is infinite, the handler substitutes a finite value.
59+
// This flag tracks whether the substitute came from SizeThatFits (a content measurement,
60+
// not a real bound). If so, the cap at the bottom must be skipped — the base already
61+
// returns the correct size. When the substitute is Bounds.Height (a real frame bound),
62+
// the flag stays false and the cap applies to preserve scrollability.
63+
bool heightSubstitutedFromSizeThatFits = false;
64+
5865
if (double.IsInfinity(widthConstraint) || double.IsInfinity(heightConstraint))
5966
{
6067
// If we drop an infinite value into base.GetDesiredSize for the Editor, we'll
@@ -72,31 +79,29 @@ public override Size GetDesiredSize(double widthConstraint, double heightConstra
7279
{
7380
var currentHeight = (double)PlatformView.Bounds.Height;
7481

75-
// NOTE: Bounds and ContentSize reflect the pre-rotation frame at this point.
76-
// The check is intentionally based on the previous layout state to detect
77-
// scrollable Editors that should not grow after cache invalidation (#35114).
78-
// When content overflows the frame and auto-growth is off, cap the height
79-
// to the current frame height to preserve scrollability after rotation (#35114).
80-
// Skip when AllowAutoGrowth is set (AutoSize=TextChanges) — Editor should grow freely.
82+
// When content overflows the current frame and auto-growth is disabled,
83+
// use Bounds.Height as the constraint to preserve scrollability after rotation.
84+
// Editors with AutoSize=TextChanges (AllowAutoGrowth=true) are exempt.
8185
if (!PlatformView.AllowAutoGrowth
8286
&& currentHeight > 0
8387
&& PlatformView.ContentSize.Height > currentHeight)
8488
{
85-
heightConstraint = currentHeight;
89+
heightConstraint = currentHeight; // real bound — cap will apply
8690
}
8791
else
8892
{
8993
heightConstraint = sizeThatFits.Height;
94+
heightSubstitutedFromSizeThatFits = true; // not a real bound — cap will be skipped
9095
}
9196
}
9297
}
9398

9499
var result = base.GetDesiredSize(widthConstraint, heightConstraint);
95100

96-
// Cap applies even for finite constraints: UITextView.SizeThatFits (UIScrollView subclass)
97-
// ignores the height argument and always returns full content height.
98-
// Capping here ensures GetDesiredSize honours the caller's constraint.
99-
if (result.Height > heightConstraint)
101+
// Clamp the result to the constraint only when it represents a real upper bound.
102+
// UITextView (a UIScrollView subclass) ignores the height in SizeThatFits and always
103+
// returns full content height, so clamping is needed for caller- or frame-derived bounds.
104+
if (!heightSubstitutedFromSizeThatFits && result.Height > heightConstraint)
100105
{
101106
return new Size(result.Width, heightConstraint);
102107
}

0 commit comments

Comments
 (0)