[Android, iOS] Fixed TimePicker FlowDirection Not Applied Across Platforms#30369
[Android, iOS] Fixed TimePicker FlowDirection Not Applied Across Platforms#30369kubaflo merged 9 commits intodotnet:inflight/currentfrom
Conversation
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull Request Overview
This PR ensures the FlowDirection property is correctly applied to TimePicker controls across iOS, Android, and Windows by updating handler mappings and platform extensions, and adds a UI test to validate the behavior.
- Unify and correct the
MapFlowDirectionsignature and mapping in handlers. - Implement platform-specific alignment logic in iOS, Android, and Windows extensions.
- Add a HostApp page and Shared.Tests UI test to verify RTL/LTR toggling.
Reviewed Changes
Copilot reviewed 10 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt | Replaced concrete overload with interface-based MapFlowDirection |
| src/Core/src/Platform/iOS/TimePickerExtensions.cs | Fixed culture usage and added text alignment logic |
| src/Core/src/Platform/Windows/TimePickerExtensions.cs | Added UpdateTextAlignment extension applying RTL/LTR at load |
| src/Core/src/Platform/Android/TimePickerExtensions.cs | Added UpdateTextAlignment extension for Android |
| src/Core/src/Handlers/TimePicker/TimePickerHandler.iOS.cs | Changed MapFlowDirection to use interface and null guard |
| src/Core/src/Handlers/TimePicker/TimePickerHandler.cs | Unified FlowDirection mapping across all platforms |
| src/Core/src/Handlers/TimePicker/TimePickerHandler.Windows.cs | Introduced internal MapFlowDirection for Windows |
| src/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cs | Introduced internal MapFlowDirection for Android |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30192.cs | Added UI test to verify FlowDirection toggling |
| src/Controls/tests/TestCases.HostApp/Issues/Issue30192.cs | Added HostApp page with toggle button for FlowDirection testing |
Comments suppressed due to low confidence (1)
src/Core/src/Platform/iOS/TimePickerExtensions.cs:79
- [nitpick] The parameter name 'textField' is ambiguous for a MauiTimePicker instance; consider renaming it to 'mauiTimePicker' or 'picker' for consistency.
public static void UpdateTextAlignment(this MauiTimePicker textField, ITimePicker timePicker)
jsuarezruiz
left a comment
There was a problem hiding this comment.
@Dhivya-SF4094 Could you rebase and fix the conflict?
8040541 to
983c12f
Compare
@jsuarezruiz Rebased and resolved conflicts. Could you please review it once? |
|
|
kubaflo
left a comment
There was a problem hiding this comment.
Could you please resolve conflicts?
983c12f to
691b7d6
Compare
|
🚀 Dogfood this PR with:
curl -fsSL https://github.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 30369Or
iex "& { $(irm https://github.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 30369" |
|
The AI summary has been validated and addressed. |
kubaflo
left a comment
There was a problem hiding this comment.
Could you please review the AI's summary?
Updated fix in TimePickerHandler.cs |
🚦 Gate — Test Before and After Fix
🚦 Gate Session —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue30192 Issue30192 |
✅ FAIL — 785s | ✅ PASS — 1343s |
🔴 Without fix — 🖥️ Issue30192: FAIL ✅ · 785s
Determining projects to restore...
Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 538 ms).
Restored /home/vsts/work/1/s/src/Essentials/src/Essentials.csproj (in 4.01 sec).
Restored /home/vsts/work/1/s/src/Core/src/Core.csproj (in 5.11 sec).
Restored /home/vsts/work/1/s/src/Core/maps/src/Maps.csproj (in 2.08 sec).
Restored /home/vsts/work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 52 ms).
Restored /home/vsts/work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 25 ms).
Restored /home/vsts/work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 27 ms).
Restored /home/vsts/work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 48 ms).
Restored /home/vsts/work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 979 ms).
Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 1.65 sec).
1 of 11 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:08:27.24
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Determining projects to restore...
Restored /home/vsts/work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 1.73 sec).
Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 8 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 5.59 sec).
Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.Android.Tests/Controls.TestCases.Android.Tests.csproj (in 7.67 sec).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 2 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 7 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 403 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 2.15 sec).
5 of 13 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.21] Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.91] Discovered: Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 04/12/2026 15:26:30 FixtureSetup for Issue30192(Android)
>>>>> 04/12/2026 15:26:33 TimePickerFlowDirectionTest Start
>>>>> 04/12/2026 15:26:40 TimePickerFlowDirectionTest Stop
>>>>> 04/12/2026 15:26:40 Log types: logcat, bugreport, server
Failed TimePickerFlowDirectionTest [8 s]
Error Message:
VisualTestUtils.VisualTestFailedException :
Snapshot different than baseline: TimePickerFlowDirectionTest.png (1.50% difference)
If the correct baseline has changed (this isn't a a bug), then update the baseline image.
See test attachment or download the build artifacts to get the new snapshot file.
More info: https://aka.ms/visual-test-workflow
Stack Trace:
at VisualTestUtils.VisualRegressionTester.Fail(String message) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 162
at VisualTestUtils.VisualRegressionTester.VerifyMatchesSnapshot(String name, ImageSnapshot actualImage, String environmentName, ITestContext testContext) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 123
at Microsoft.Maui.TestCases.Tests.UITest.<VerifyScreenshot>g__Verify|13_0(String name, <>c__DisplayClass13_0&) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 477
at Microsoft.Maui.TestCases.Tests.UITest.VerifyScreenshot(String name, Nullable`1 retryDelay, Nullable`1 retryTimeout, Int32 cropLeft, Int32 cropRight, Int32 cropTop, Int32 cropBottom, Double tolerance) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 309
at Microsoft.Maui.TestCases.Tests.Issues.Issue30192.TimePickerFlowDirectionTest() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30192.cs:line 21
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
NUnit Adapter 4.5.0.0: Test execution complete
Total tests: 1
Failed: 1
Test Run Failed.
Total time: 1.5095 Minutes
🟢 With fix — 🖥️ Issue30192: PASS ✅ · 1343s
(truncated to last 15,000 chars)
/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.RunInstall() [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
Build FAILED.
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: Mono.AndroidTools.InstallFailedException: Unexpected install output: cmd: Failure calling service package: Broken pipe (32) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Mono.AndroidTools.AndroidDevice.<>c__DisplayClass105_0.<InstallPackage>b__0(Task`1 t) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.RunInstall() [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
0 Warning(s)
1 Error(s)
Time Elapsed 00:11:29.73
* daemon not running; starting now at tcp:5037
* daemon started successfully
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:08:36.52
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13813202
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.12] Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.35] Discovered: Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 04/12/2026 15:49:01 FixtureSetup for Issue30192(Android)
>>>>> 04/12/2026 15:49:03 TimePickerFlowDirectionTest Start
>>>>> 04/12/2026 15:49:07 TimePickerFlowDirectionTest Stop
Passed TimePickerFlowDirectionTest [4 s]
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Successful.
Total tests: 1
Passed: 1
Total time: 23.6663 Seconds
📁 Fix files reverted (6 files)
eng/pipelines/ci-copilot.ymlsrc/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cssrc/Core/src/Handlers/TimePicker/TimePickerHandler.cssrc/Core/src/Handlers/TimePicker/TimePickerHandler.iOS.cssrc/Core/src/Platform/Android/TimePickerExtensions.cssrc/Core/src/Platform/iOS/TimePickerExtensions.cs
🤖 AI Summary
📊 Review Session —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #30369 | Add internal MapFlowDirection(ITimePickerHandler) overloads for iOS+Android; implement UpdateTextAlignment on both platforms |
✅ PASSED (Gate, Android) | TimePickerHandler.cs, .Android.cs, .iOS.cs, TimePickerExtensions.cs ×2 |
Original PR |
🔧 Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #30369 | Add internal MapFlowDirection(ITimePickerHandler) overloads iOS+Android; add UpdateTextAlignment extension; 12h/24h conditional logic |
✅ PASSED (Gate) | 5 files | Original PR; handles 12h vs 24h format |
| 1 | claude-opus-4.6 | Add MauiTimePicker dispatch in ViewExtensions.UpdateFlowDirection → new TimePickerExtensions.UpdateFlowDirection overload (base + TextAlignment) |
✅ PASS | 2 files | No handler changes; TimePicker-specific dispatch |
| 2 | claude-sonnet-4.6 | Modify TextViewExtensions.UpdateFlowDirection to set TextAlignment for any EditText subclass (atomically with LayoutDirection) |
✅ PASS | 1 file | Fixes ALL EditText subclasses; cleanest/smallest |
| 3 | gpt-5.3-codex | Handler lifecycle approach (subscribe to events in ConnectHandler) | ❌ FAIL | - | RS0016 errors; visual diff 2.12%; ITimePicker lacks PropertyChanged |
| 4 | gpt-5.4 | Set TextAlignment = ViewStart in MauiTimePicker constructor |
✅ PASS | 1 file | Relies on ViewStart respecting LayoutDirection; elegant but different mechanism |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-sonnet-4.6 | 2 | Yes | Override OnRtlPropertiesChanged in MauiTimePicker — but Attempt 3 already tried this (hit RS0016) |
| claude-opus-4.6 | 2 | No | Solution space thoroughly covered |
| gpt-5.3-codex | 2 | No | All reasonable approaches covered |
Exhausted: Yes
Selected Fix: PR #30369 — The PR's approach is most appropriate because:
- It's semantically correct: Registers
MapFlowDirectionexplicitly in the mapper for Android, making the intent clear - It handles format-specific behavior: 12h vs 24h distinction is TimePicker-specific logic that belongs in the TimePicker handler
- It mirrors the iOS fix pattern: Consistent approach across both platforms
- Attempt 2 (
TextViewExtensionsfix) is simpler and would also work, but it modifies shared code for ALL EditText subclasses which carries broader regression risk than a targeted TimePicker fix
📋 Report — Final Recommendation
⚠️ Final Recommendation: REQUEST CHANGES
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | ✅ COMPLETE | Issue #30192, 5 impl files + 2 test files + 3 snapshots |
| Gate | ✅ PASSED | Android — tests fail without fix, pass with fix |
| Try-Fix | ✅ COMPLETE | 4 attempts: 3 passing alternatives found (Attempts 1, 2, 4) |
| Report | ✅ COMPLETE |
Summary
PR #30369 correctly fixes TimePicker.FlowDirection not being applied on Android and iOS. The root cause analysis is accurate, the approach is valid, and the Gate passes on Android. However, there is a bug in the Android UpdateTextAlignment implementation: it doesn't handle FlowDirection.MatchParent, causing incorrect alignment when a TimePicker inherits RTL direction from a parent. Additionally, the try-fix exploration found a simpler 1-file alternative (Attempt 2) worth noting.
Root Cause
- iOS:
MapFlowDirectionin the mapper resolved toViewHandler.MapFlowDirection(via the base class) because the only iOS overload tookTimePickerHandler(concrete type), notITimePickerHandler. This is not compatible withAction<ITimePickerHandler, ITimePicker>, so text alignment was never applied. - Android:
MapFlowDirectionwas simply not registered in the mapper for Android at all.ViewHandler.MapFlowDirection(inherited) calledUpdateFlowDirectionwhich setsLayoutDirection/TextDirectionbut NOTTextAlignment, leaving AM/PM text mis-aligned in 12-hour RTL.
Fix Quality
What's correct:
- Adding
internal static MapFlowDirection(ITimePickerHandler, ITimePicker)overloads for both platforms correctly connects the mapper to platform-specific logic - The iOS
UpdateTextAlignmentcorrectly readsSemanticContentAttribute(set byUpdateFlowDirection) to determine effective alignment — this correctly resolvesMatchParenton iOS - The 12h vs 24h format distinction on Android is reasonable —
UpdateFlowDirectionalone handles 24h purely-numeric content - Tests are properly scoped with
#if TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS
Bug — FlowDirection.MatchParent not handled on Android:
UpdateTextAlignment in TimePickerExtensions.cs (Android) reads the raw timePicker.FlowDirection:
mauiTimePicker.TextAlignment = timePicker.FlowDirection == FlowDirection.RightToLeft
? ATextAlignment.TextEnd
: ATextAlignment.TextStart; // ← BUG: also used for MatchParentWhen FlowDirection = MatchParent and the parent is RTL, UpdateFlowDirection correctly sets LayoutDirection = Inherit, but UpdateTextAlignment sets TextAlignment = TextStart (absolute LTR). The text would be left-aligned when it should follow the RTL parent.
Suggested fix — use ViewStart for the non-RTL fallback (respects inherited LayoutDirection):
internal static void UpdateTextAlignment(this MauiTimePicker mauiTimePicker, ITimePicker timePicker)
{
mauiTimePicker.TextAlignment = timePicker.FlowDirection == FlowDirection.RightToLeft
? ATextAlignment.TextEnd
: ATextAlignment.ViewStart; // ViewStart respects LayoutDirection (covers both LTR and MatchParent)
}ViewStart in an LTR context still aligns left, so there is no behavior change for LeftToRight while correctly handling MatchParent.
Simpler alternative noted (FYI):
Try-Fix Attempt 2 found that modifying TextViewExtensions.UpdateFlowDirection (1 file, shared) to set TextAlignment for any EditText subclass produces the same fix result with fewer files changed. The PR's approach is preferred for its precision and explicit intent, but the team may want to evaluate the broader approach for consistency with DatePicker and Entry.
Selected Fix
Selected Fix: PR (with the MatchParent fix above applied)
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
…forms (#30369) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Detail The FlowDirection property is not respected by the TimePicker control. Setting FlowDirection="RightToLeft" has no visual effect on the control across any platform. ### Root Cause iOS: The MapFlowDirection method incorrectly used the concrete TimePickerHandler type instead of the ITimePickerHandler interface. This bypassed platform-specific logic and defaulted to ViewHandler.MapFlowDirection, which lacked the necessary text alignment handling. Android: The FlowDirection property was not correctly mapped to the native implementation, resulting in incorrect or missing text alignment updates. ### Description of Change iOS: Updated the MapFlowDirection method to use the correct handler interface. Implemented alignment logic in TimePickerExtensions.cs using EffectiveFlowDirection to properly align text for both RTL and LTR layouts. Android: Implemented a platform-specific MapFlowDirection method in TimePickerHandler.Android.cs: For 12-hour format, UpdateTextAlignment is applied to align localized "AM/PM" text based on FlowDirection. For 24-hour format, alignment is handled via UpdateFlowDirection, which sets LayoutDirection and TextDirection to align purely numeric content Validated the behaviour in the following platforms - [x] Android - [ ] Windows #30322 - [x] iOS - [ ] Mac #30322 ### Issues Fixed: Fixes #30192 ### Screenshots | Before | After | |---------|--------| | <img src="https://github.com/user-attachments/assets/37c4a442-1011-4c23-bc2e-8743bc11adc7"> | <img src="https://github.com/user-attachments/assets/91b69287-b8eb-4d40-b8a1-0734ef1f89db"> |
…forms (dotnet#30369) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Detail The FlowDirection property is not respected by the TimePicker control. Setting FlowDirection="RightToLeft" has no visual effect on the control across any platform. ### Root Cause iOS: The MapFlowDirection method incorrectly used the concrete TimePickerHandler type instead of the ITimePickerHandler interface. This bypassed platform-specific logic and defaulted to ViewHandler.MapFlowDirection, which lacked the necessary text alignment handling. Android: The FlowDirection property was not correctly mapped to the native implementation, resulting in incorrect or missing text alignment updates. ### Description of Change iOS: Updated the MapFlowDirection method to use the correct handler interface. Implemented alignment logic in TimePickerExtensions.cs using EffectiveFlowDirection to properly align text for both RTL and LTR layouts. Android: Implemented a platform-specific MapFlowDirection method in TimePickerHandler.Android.cs: For 12-hour format, UpdateTextAlignment is applied to align localized "AM/PM" text based on FlowDirection. For 24-hour format, alignment is handled via UpdateFlowDirection, which sets LayoutDirection and TextDirection to align purely numeric content Validated the behaviour in the following platforms - [x] Android - [ ] Windows dotnet#30322 - [x] iOS - [ ] Mac dotnet#30322 ### Issues Fixed: Fixes dotnet#30192 ### Screenshots | Before | After | |---------|--------| | <img src="https://github.com/user-attachments/assets/37c4a442-1011-4c23-bc2e-8743bc11adc7"> | <img src="https://github.com/user-attachments/assets/91b69287-b8eb-4d40-b8a1-0734ef1f89db"> |
…forms (#30369) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Detail The FlowDirection property is not respected by the TimePicker control. Setting FlowDirection="RightToLeft" has no visual effect on the control across any platform. ### Root Cause iOS: The MapFlowDirection method incorrectly used the concrete TimePickerHandler type instead of the ITimePickerHandler interface. This bypassed platform-specific logic and defaulted to ViewHandler.MapFlowDirection, which lacked the necessary text alignment handling. Android: The FlowDirection property was not correctly mapped to the native implementation, resulting in incorrect or missing text alignment updates. ### Description of Change iOS: Updated the MapFlowDirection method to use the correct handler interface. Implemented alignment logic in TimePickerExtensions.cs using EffectiveFlowDirection to properly align text for both RTL and LTR layouts. Android: Implemented a platform-specific MapFlowDirection method in TimePickerHandler.Android.cs: For 12-hour format, UpdateTextAlignment is applied to align localized "AM/PM" text based on FlowDirection. For 24-hour format, alignment is handled via UpdateFlowDirection, which sets LayoutDirection and TextDirection to align purely numeric content Validated the behaviour in the following platforms - [x] Android - [ ] Windows #30322 - [x] iOS - [ ] Mac #30322 ### Issues Fixed: Fixes #30192 ### Screenshots | Before | After | |---------|--------| | <img src="https://github.com/user-attachments/assets/37c4a442-1011-4c23-bc2e-8743bc11adc7"> | <img src="https://github.com/user-attachments/assets/91b69287-b8eb-4d40-b8a1-0734ef1f89db"> |
…forms (#30369) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Detail The FlowDirection property is not respected by the TimePicker control. Setting FlowDirection="RightToLeft" has no visual effect on the control across any platform. ### Root Cause iOS: The MapFlowDirection method incorrectly used the concrete TimePickerHandler type instead of the ITimePickerHandler interface. This bypassed platform-specific logic and defaulted to ViewHandler.MapFlowDirection, which lacked the necessary text alignment handling. Android: The FlowDirection property was not correctly mapped to the native implementation, resulting in incorrect or missing text alignment updates. ### Description of Change iOS: Updated the MapFlowDirection method to use the correct handler interface. Implemented alignment logic in TimePickerExtensions.cs using EffectiveFlowDirection to properly align text for both RTL and LTR layouts. Android: Implemented a platform-specific MapFlowDirection method in TimePickerHandler.Android.cs: For 12-hour format, UpdateTextAlignment is applied to align localized "AM/PM" text based on FlowDirection. For 24-hour format, alignment is handled via UpdateFlowDirection, which sets LayoutDirection and TextDirection to align purely numeric content Validated the behaviour in the following platforms - [x] Android - [ ] Windows #30322 - [x] iOS - [ ] Mac #30322 ### Issues Fixed: Fixes #30192 ### Screenshots | Before | After | |---------|--------| | <img src="https://github.com/user-attachments/assets/37c4a442-1011-4c23-bc2e-8743bc11adc7"> | <img src="https://github.com/user-attachments/assets/91b69287-b8eb-4d40-b8a1-0734ef1f89db"> |
…forms (#30369) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Detail The FlowDirection property is not respected by the TimePicker control. Setting FlowDirection="RightToLeft" has no visual effect on the control across any platform. ### Root Cause iOS: The MapFlowDirection method incorrectly used the concrete TimePickerHandler type instead of the ITimePickerHandler interface. This bypassed platform-specific logic and defaulted to ViewHandler.MapFlowDirection, which lacked the necessary text alignment handling. Android: The FlowDirection property was not correctly mapped to the native implementation, resulting in incorrect or missing text alignment updates. ### Description of Change iOS: Updated the MapFlowDirection method to use the correct handler interface. Implemented alignment logic in TimePickerExtensions.cs using EffectiveFlowDirection to properly align text for both RTL and LTR layouts. Android: Implemented a platform-specific MapFlowDirection method in TimePickerHandler.Android.cs: For 12-hour format, UpdateTextAlignment is applied to align localized "AM/PM" text based on FlowDirection. For 24-hour format, alignment is handled via UpdateFlowDirection, which sets LayoutDirection and TextDirection to align purely numeric content Validated the behaviour in the following platforms - [x] Android - [ ] Windows #30322 - [x] iOS - [ ] Mac #30322 ### Issues Fixed: Fixes #30192 ### Screenshots | Before | After | |---------|--------| | <img src="https://github.com/user-attachments/assets/37c4a442-1011-4c23-bc2e-8743bc11adc7"> | <img src="https://github.com/user-attachments/assets/91b69287-b8eb-4d40-b8a1-0734ef1f89db"> |
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Issue Detail
The FlowDirection property is not respected by the TimePicker control. Setting FlowDirection="RightToLeft" has no visual effect on the control across any platform.
Root Cause
iOS: The MapFlowDirection method incorrectly used the concrete TimePickerHandler type instead of the ITimePickerHandler interface. This bypassed platform-specific logic and defaulted to ViewHandler.MapFlowDirection, which lacked the necessary text alignment handling.
Android: The FlowDirection property was not correctly mapped to the native implementation, resulting in incorrect or missing text alignment updates.
Description of Change
iOS: Updated the MapFlowDirection method to use the correct handler interface. Implemented alignment logic in TimePickerExtensions.cs using EffectiveFlowDirection to properly align text for both RTL and LTR layouts.
Android: Implemented a platform-specific MapFlowDirection method in TimePickerHandler.Android.cs:
For 12-hour format, UpdateTextAlignment is applied to align localized "AM/PM" text based on FlowDirection.
For 24-hour format, alignment is handled via UpdateFlowDirection, which sets LayoutDirection and TextDirection to align purely numeric content
Validated the behaviour in the following platforms
Issues Fixed:
Fixes #30192
Screenshots