From f8623745d3b933e1f3b8f1235d7a52d6cbe95f12 Mon Sep 17 00:00:00 2001 From: praveenkumarkarunanithi <100338903+praveenkumarkarunanithi@users.noreply.github.com> Date: Tue, 6 Jan 2026 03:49:12 +0530 Subject: [PATCH 01/18] [Android] Fix for Label WordWrap width issue causing HorizontalOptions misalignment (#33281) ### Root Cause On Android, for `Label` controls with `LineBreakMode="WordWrap"` and multiple lines, `GetDesiredSize()` returns the full constraint width instead of the actual rendered text width. This causes extra trailing space and incorrect horizontal alignment when `HorizontalLayoutAlignment` is set to `Start`, `Center`, or `End`. Single-line and Fill alignment cases are unaffected. ### Description of Change Updated `GetDesiredSize()` in `LabelHandler.Android.cs` to calculate the actual content width for wrapped, multi-line labels with non-Fill alignment. The implementation determines the widest rendered line using `layout.GetLineWidth(i)` and uses that value (plus padding) as the desired width. ### Issues Fixed Fixes #31782 Fixes #27614 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Output Video | Before Issue Fix | After Issue Fix | |------------------|-----------------| | withoutfix | withfix | --- .../WordWrapLineBreakModeNoExtraSpace.png | Bin 29550 -> 29567 bytes .../TestCases.HostApp/Issues/Issue31782.cs | 34 ++++++++++++++++++ .../Tests/Issues/Issue31782.cs | 25 +++++++++++++ .../Handlers/Label/LabelHandler.Android.cs | 30 ++++++++++++++++ .../net-android/PublicAPI.Unshipped.txt | 1 + 5 files changed, 90 insertions(+) create mode 100644 src/Controls/tests/TestCases.HostApp/Issues/Issue31782.cs create mode 100644 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31782.cs diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/WordWrapLineBreakModeNoExtraSpace.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/WordWrapLineBreakModeNoExtraSpace.png index 043b5348f47eb803d2c79fa7c627efb9fcdc9a86..02ff38e545c3eea32fa34d3fbd92de0a9df2657a 100644 GIT binary patch literal 29567 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 literal 29550 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 A(f|Me diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue31782.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue31782.cs new file mode 100644 index 000000000000..987355f98900 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue31782.cs @@ -0,0 +1,34 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 31782, "Unexpected Line Breaks in Android, Label with WordWrap Mode Due to Trailing Space", PlatformAffected.Android)] +public class Issue31782 : ContentPage +{ + public Issue31782() + { + var layout = new VerticalStackLayout { Spacing = 20, Padding = 20 }; + + var container = new Grid + { + AutomationId = "Container", + WidthRequest = 300, + HorizontalOptions = LayoutOptions.Center, + BackgroundColor = Colors.LightBlue + }; + + var label = new Label + { + AutomationId = "TestLabel", + Text = "How does .NET MAUI handle mauinavigaton?", + LineBreakMode = LineBreakMode.WordWrap, + TextColor = Color.FromArgb("#212121"), + FontSize = 20, + HorizontalOptions = LayoutOptions.End, + BackgroundColor = Colors.LightGreen + }; + + container.Add(label); + layout.Add(container); + + Content = layout; + } +} diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31782.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31782.cs new file mode 100644 index 000000000000..b4e684ef76ec --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31782.cs @@ -0,0 +1,25 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue31782 : _IssuesUITest +{ + public Issue31782(TestDevice device) : base(device) { } + + public override string Issue => "Unexpected Line Breaks in Android, Label with WordWrap Mode Due to Trailing Space"; + + [Test] + [Category(UITestCategories.Label)] + public void LabelWithEndAlignmentShouldNotHaveTrailingSpace() + { + var labelRect = App.WaitForElement("TestLabel").GetRect(); + var containerRect = App.WaitForElement("Container").GetRect(); + + // Before fix: Label width ≈ container width (300pt with trailing space) + // After fix: Label width < container width (measures only longest line) + Assert.That(labelRect.Width, Is.LessThan(containerRect.Width - 10), + $"End-aligned label ({labelRect.Width}pt) should be narrower than container ({containerRect.Width}pt)"); + } +} diff --git a/src/Core/src/Handlers/Label/LabelHandler.Android.cs b/src/Core/src/Handlers/Label/LabelHandler.Android.cs index ac4f3fd7d229..d70b114984d7 100644 --- a/src/Core/src/Handlers/Label/LabelHandler.Android.cs +++ b/src/Core/src/Handlers/Label/LabelHandler.Android.cs @@ -1,3 +1,4 @@ +using Android.Text; using Android.Views; using AndroidX.AppCompat.Widget; using Microsoft.Maui.Graphics; @@ -15,6 +16,35 @@ public override void PlatformArrange(Rect frame) base.PlatformArrange(frame); } + public override Size GetDesiredSize(double widthConstraint, double heightConstraint) + { + var size = base.GetDesiredSize(widthConstraint, heightConstraint); + + // Android TextView reports full available width instead of actual text width when + // text wraps to multiple lines, causing incorrect positioning for non-Fill alignments. + if (VirtualView.HorizontalLayoutAlignment != Primitives.LayoutAlignment.Fill && + PlatformView?.Layout is Layout layout && + layout.LineCount > 1) + { + float maxLineWidth = 0; + for (int i = 0; i < layout.LineCount; i++) + { + float lineWidth = layout.GetLineWidth(i); + if (lineWidth > maxLineWidth) + maxLineWidth = lineWidth; + } + + if (maxLineWidth > 0) + { + var actualWidth = Context.FromPixels(maxLineWidth + PlatformView.PaddingLeft + PlatformView.PaddingRight); + if (actualWidth < size.Width) + return new Size(actualWidth, size.Height); + } + } + + return size; + } + internal static void MapBackground(ILabelHandler handler, ILabel label) { handler.PlatformView?.UpdateBackground(label); diff --git a/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt index 7dc5c58110bf..ebf19fa9dfd5 100644 --- a/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt +++ b/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt @@ -1 +1,2 @@ #nullable enable +override Microsoft.Maui.Handlers.LabelHandler.GetDesiredSize(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size From f466cbe977c1a82a2e69eef71741ace7fc442572 Mon Sep 17 00:00:00 2001 From: Subhiksha Chandrasekaran Date: Tue, 6 Jan 2026 04:37:03 +0530 Subject: [PATCH 02/18] [iOS & Catalyst ] Fixed IsEnabled property should work on Tabs (#33369) ### Root Cause The load-time handling of the `IsEnabled` property for tab items was not implemented on iOS. As a result, disabled tabs could still be selectable and navigateable ### Description of Change Updated `ShellItemRenderer.cs` to set the `IsEnabled` property of each `TabBar` item based on the corresponding `IsEnabled` value during both initial creation and when the items collection changes. ### Issues Fixed Fixes #33158 ### Follow-up PR : - On **iOS 26** and **Catalyst 26**, navigation between tabs via drag and selection gestures is handled separately in this PR https://github.com/dotnet/maui/pull/33337. ### Tested the behavior in the following platforms - [ ] Windows - [x] Android - [x] iOS - [x] Mac | Before Issue Fix | After Issue Fix | |----------|----------| |