diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/LabelWordWrapNotClippedWithRtlFlowDirection.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/LabelWordWrapNotClippedWithRtlFlowDirection.png new file mode 100644 index 000000000000..67ace78f0c20 Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/LabelWordWrapNotClippedWithRtlFlowDirection.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue34459.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue34459.cs new file mode 100644 index 000000000000..93f8aa5eba2f --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue34459.cs @@ -0,0 +1,29 @@ +namespace Maui.Controls.Sample.Issues +{ + [Issue(IssueTracker.Github, 34459, "Android Label word wrapping clips text depending on alignment and layout options", PlatformAffected.Android)] + public class Issue34459 : ContentPage + { + public Issue34459() + { + var rtlLabel = new Label + { + Text = "Hello, World!", + VerticalOptions = LayoutOptions.Start, + HorizontalOptions = LayoutOptions.Start, + HorizontalTextAlignment = TextAlignment.Start, + LineBreakMode = LineBreakMode.WordWrap, + FontSize = 32, + AutomationId = "RtlLabel", + }; + + Content = new VerticalStackLayout + { + BackgroundColor = Colors.Gray, + FlowDirection = FlowDirection.RightToLeft, + WidthRequest = 150, + AutomationId = "RtlContainer", + Children = { rtlLabel }, + }; + } + } +} diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34459.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34459.cs new file mode 100644 index 000000000000..fe168e0cff09 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34459.cs @@ -0,0 +1,22 @@ +#if TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST // https://github.com/dotnet/maui/issues/34531 +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue34459 : _IssuesUITest +{ + public override string Issue => "Android Label word wrapping clips text depending on alignment and layout options"; + + public Issue34459(TestDevice device) : base(device) { } + + [Test] + [Category(UITestCategories.Label)] + public void LabelWordWrapNotClippedWithRtlFlowDirection() + { + App.WaitForElement("RtlLabel"); + VerifyScreenshot(); + } +} +#endif \ No newline at end of file diff --git a/src/Core/src/Handlers/Label/LabelHandler.Android.cs b/src/Core/src/Handlers/Label/LabelHandler.Android.cs index dedc829ac70b..26a3017ae2fa 100644 --- a/src/Core/src/Handlers/Label/LabelHandler.Android.cs +++ b/src/Core/src/Handlers/Label/LabelHandler.Android.cs @@ -30,15 +30,32 @@ public override Size GetDesiredSize(double widthConstraint, double heightConstra PlatformView.Ellipsize == null) { float maxLineWidth = 0; + float maxLineRight = 0; for (int i = 0; i < layout.LineCount; i++) { float lineWidth = layout.GetLineWidth(i); if (lineWidth > maxLineWidth) maxLineWidth = lineWidth; + + // GetLineRight() captures the true visual right edge, including RTL/bidi + // offsets that GetLineWidth() can under-report for non-left-anchored text. + float lineRight = layout.GetLineRight(i); + if (lineRight > maxLineRight) + { + maxLineRight = lineRight; + } } if (maxLineWidth > 0) { + // If any line's visual right edge exceeds the computed content width, + // narrowing to that width would clip the text (e.g. RTL/bidi in an RTL + // container). Return the original size without an extra measure pass. + if (maxLineRight > maxLineWidth) + { + return size; + } + var actualWidth = Context.FromPixels(maxLineWidth + PlatformView.PaddingLeft + PlatformView.PaddingRight); if (actualWidth < size.Width) {