Skip to content

[Android, iOS] Fixed TimePicker FlowDirection Not Applied Across Platforms#30369

Merged
kubaflo merged 9 commits intodotnet:inflight/currentfrom
Dhivya-SF4094:fix-30192
Apr 13, 2026
Merged

[Android, iOS] Fixed TimePicker FlowDirection Not Applied Across Platforms#30369
kubaflo merged 9 commits intodotnet:inflight/currentfrom
Dhivya-SF4094:fix-30192

Conversation

@Dhivya-SF4094
Copy link
Copy Markdown
Contributor

@Dhivya-SF4094 Dhivya-SF4094 commented Jul 2, 2025

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

Before  After 
     

@dotnet-policy-service dotnet-policy-service Bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Jul 2, 2025
@jsuarezruiz jsuarezruiz added the area-controls-datetimepicker DatePicker, TimePicker label Jul 2, 2025
@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run MAUI-UITests-public

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@Dhivya-SF4094 Dhivya-SF4094 marked this pull request as ready for review July 3, 2025 07:51
Copilot AI review requested due to automatic review settings July 3, 2025 07:51
@Dhivya-SF4094 Dhivya-SF4094 requested a review from a team as a code owner July 3, 2025 07:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 MapFlowDirection signature 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)

Comment thread src/Core/src/Platform/iOS/TimePickerExtensions.cs Outdated
Comment thread src/Core/src/Platform/Windows/TimePickerExtensions.cs Outdated
Comment thread src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt Outdated
Copy link
Copy Markdown
Contributor

@jsuarezruiz jsuarezruiz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Dhivya-SF4094 Could you rebase and fix the conflict?

@Dhivya-SF4094
Copy link
Copy Markdown
Contributor Author

@Dhivya-SF4094 Could you rebase and fix the conflict?

@jsuarezruiz Rebased and resolved conflicts. Could you please review it once?

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 21, 2026

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please resolve conflicts?

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 23, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://github.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 30369

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://github.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 30369"

@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 24, 2026
@Dhivya-SF4094
Copy link
Copy Markdown
Contributor Author

The AI summary has been validated and addressed.

@kubaflo kubaflo added the s/agent-suggestions-implemented Maintainer applies when PR author adopts agent's recommendation label Mar 24, 2026
@MauiBot MauiBot added s/agent-fix-win AI found a better alternative fix than the PR and removed s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates labels Mar 26, 2026
@MauiBot MauiBot added s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) s/agent-changes-requested AI agent recommends changes - found a better alternative or issues and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) labels Mar 27, 2026
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please review the AI's summary?

@Dhivya-SF4094
Copy link
Copy Markdown
Contributor Author

Could you please review the AI's summary?

Updated fix in TimePickerHandler.cs

@dotnet dotnet deleted a comment from MauiBot Apr 12, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 12, 2026
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 12, 2026

🚦 Gate — Test Before and After Fix

👋 @Dhivya-SF4094 — new gate results are available. Please review the latest session below.

🚦 Gate Session5b4855a · Updated TimePickerHandler · 2026-04-12 15:49 UTC

Gate Result: ✅ PASSED

Platform: ANDROID · Base: main · Merge base: b43bdad1

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.yml
  • src/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cs
  • src/Core/src/Handlers/TimePicker/TimePickerHandler.cs
  • src/Core/src/Handlers/TimePicker/TimePickerHandler.iOS.cs
  • src/Core/src/Platform/Android/TimePickerExtensions.cs
  • src/Core/src/Platform/iOS/TimePickerExtensions.cs

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 12, 2026

🤖 AI Summary

👋 @Dhivya-SF4094 — new AI review results are available. Please review the latest session below.

📊 Review Session5b4855a · Updated TimePickerHandler · 2026-04-12 16:56 UTC
🔍 Pre-Flight — Context & Validation

Issue: #30192 - TimePicker FlowDirection Not Working on All Platforms
PR: #30369 - [Android, iOS] Fixed TimePicker FlowDirection Not Applied Across Platforms
Platforms Affected: Android (gate tested), iOS (untested in gate), Windows/macOS tracked separately in #30322
Files Changed: 5 implementation, 2 test, 3 snapshots

Key Findings

  • Root bug on iOS: MapFlowDirection was registered in the Mapper but the only iOS overload took TimePickerHandler (concrete type), which is NOT convertible to Action<ITimePickerHandler, ITimePicker>. The compiler fell back to ViewHandler.MapFlowDirection which lacked text alignment handling.
  • Root bug on Android: MapFlowDirection was not registered in the mapper at all (only registered for iOS before). No platform-specific flow direction logic existed.
  • iOS fix: Adds internal static MapFlowDirection(ITimePickerHandler, ITimePicker) overload that calls UpdateFlowDirection + UpdateTextAlignment. Updates UpdateTextAlignment to read SemanticContentAttribute (set by UpdateFlowDirection) to determine text alignment.
  • Android fix: Adds internal static MapFlowDirection(ITimePickerHandler, ITimePicker) that calls UpdateFlowDirection. For 12-hour format, also calls UpdateTextAlignment to align AM/PM text.
  • Android UpdateTextAlignment: Sets TextAlignment.TextEnd for RTL, TextAlignment.TextStart otherwise. Does NOT handle FlowDirection.MatchParent (defaults to LTR even if parent is RTL).
  • iOS UpdateTextAlignment: Only explicitly maps ForceRightToLeft → Right; all other SemanticContentAttribute values → Left. Could be incorrect for Unspecified in an RTL locale.
  • Duplicate MapFlowDirection on iOS: Two methods now coexist — public static MapFlowDirection(TimePickerHandler, ITimePicker) (pre-existing, for subclass compatibility) and internal static MapFlowDirection(ITimePickerHandler, ITimePicker) (new, used by mapper). Comment says to remove the concrete overload in .NET 11.
  • 24-hour format on Android: UpdateTextAlignment is skipped when Use24HourView == true. For 24-hour, UpdateFlowDirection sets LayoutDirection/TextDirection which is sufficient for purely numeric content.
  • Test only covers 12-hour format ("hh:mm tt"). No coverage for 24-hour format on Android.
  • Gate result: ✅ PASSED on Android.

Prior Agent Reviews

  • Labels s/agent-reviewed, s/agent-changes-requested, s/agent-fix-win, s/agent-suggestions-implemented indicate prior review sessions.
  • Inline review threads (now resolved): SemanticContentAttribute vs EffectiveFlowDirection; magic string; PublicAPI.Unshipped.txt changes. All resolved by the PR author.

Fix Candidates

# 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:

  1. It's semantically correct: Registers MapFlowDirection explicitly in the mapper for Android, making the intent clear
  2. It handles format-specific behavior: 12h vs 24h distinction is TimePicker-specific logic that belongs in the TimePicker handler
  3. It mirrors the iOS fix pattern: Consistent approach across both platforms
  4. Attempt 2 (TextViewExtensions fix) 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: MapFlowDirection in the mapper resolved to ViewHandler.MapFlowDirection (via the base class) because the only iOS overload took TimePickerHandler (concrete type), not ITimePickerHandler. This is not compatible with Action<ITimePickerHandler, ITimePicker>, so text alignment was never applied.
  • Android: MapFlowDirection was simply not registered in the mapper for Android at all. ViewHandler.MapFlowDirection (inherited) called UpdateFlowDirection which sets LayoutDirection/TextDirection but NOT TextAlignment, 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 UpdateTextAlignment correctly reads SemanticContentAttribute (set by UpdateFlowDirection) to determine effective alignment — this correctly resolves MatchParent on iOS
  • The 12h vs 24h format distinction on Android is reasonable — UpdateFlowDirection alone 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 MatchParent

When 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)


@MauiBot MauiBot added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-win AI found a better alternative fix than the PR labels Apr 12, 2026
@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented Apr 12, 2026

/azp run maui-pr-uitests, maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@kubaflo kubaflo changed the base branch from main to inflight/current April 13, 2026 11:28
@kubaflo kubaflo merged commit 9f53283 into dotnet:inflight/current Apr 13, 2026
161 of 168 checks passed
PureWeen pushed a commit that referenced this pull request Apr 14, 2026
…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"> 
|
devanathan-vaithiyanathan pushed a commit to Tamilarasan-Paranthaman/maui that referenced this pull request Apr 21, 2026
…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"> 
|
PureWeen pushed a commit that referenced this pull request Apr 22, 2026
…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"> 
|
PureWeen pushed a commit that referenced this pull request Apr 28, 2026
…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"> 
|
PureWeen pushed a commit that referenced this pull request Apr 29, 2026
…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"> 
|
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-datetimepicker DatePicker, TimePicker community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) s/agent-suggestions-implemented Maintainer applies when PR author adopts agent's recommendation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TimePicker FlowDirection Not Working on All Platforms

8 participants