Skip to content

Fixed the Picker didn't dismiss it when tapping outside on iOS and MacCatalyst platform.#30067

Merged
kubaflo merged 9 commits into
dotnet:inflight/currentfrom
KarthikRajaKalaimani:fix-19168
Mar 30, 2026
Merged

Fixed the Picker didn't dismiss it when tapping outside on iOS and MacCatalyst platform.#30067
kubaflo merged 9 commits into
dotnet:inflight/currentfrom
KarthikRajaKalaimani:fix-19168

Conversation

@KarthikRajaKalaimani

Copy link
Copy Markdown
Contributor

Issue Details:

Tapping outside the Picker does not dismiss it on iOS and Mac, whereas it works as expected on Android and Windows.

Root Cause:

The touch handling for taps outside the picker was not implemented, which is why the picker was not being dismissed as expected on iOS and Mac platform.

Description of Change:

To resolve this issue, a tap gesture recognizer was added to the window containing the Picker. This allows the system to detect taps outside the Picker and dismiss it appropriately. The gesture recognizer is added during the OnStarted event and properly removed and disposed of in the OnEnded event and Disconnect methods. This implementation has been applied and successfully verified on both iOS and macOS platforms.

Tested the behavior in the following platforms.

  • Android
  • Windows
  • iOS
  • Mac

Reference:

N/A

Issues Fixed:

Fixes #19168

Screenshots

Before After
Screen.Recording.2025-06-19.at.3.46.23.PM.mov
Screen.Recording.2025-06-19.at.3.44.26.PM.mov

@dotnet-policy-service dotnet-policy-service Bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Jun 19, 2025

_tapGestureRecognizer = new UITapGestureRecognizer(() =>
{
picker.EndEditing(true);

@bhavanesh2001 bhavanesh2001 Jun 19, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Strong reference to platform view in gesture handler is asking for trouble.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Strong reference to platform view in gesture handler is asking for trouble.

Thanks for the suggestion. I have corrected it.

{
picker.EndEditing(true);
});
_tapGestureRecognizer.CancelsTouchesInView = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

CancelsTouchesInView = false lets taps through, but this gesture may dismiss the picker before "Done" is tapped, which can prevent selection from committing, please verify.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Tested this scenario and confirmed that it works as expected — the SelectedItem property retains its value when tapping outside the Picker.

@KarthikRajaKalaimani KarthikRajaKalaimani marked this pull request as ready for review June 19, 2025 13:14
@KarthikRajaKalaimani KarthikRajaKalaimani requested a review from a team as a code owner June 19, 2025 13:14
@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).

#elif IOS
App.Tap("Button");
#endif
VerifyScreenshot();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pending snapshot on Mac:
image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Pending snapshot on Mac: image

I have added the Mac snapshot.

@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).

@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).

@bhavanesh2001 bhavanesh2001 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@KarthikRajaKalaimani Thanks for the changes

Adding a gesture recognizer to the Window solely to dismiss the picker when tapping outside feels excessive, especially since not dismissing appears to be the default behavior. Are we even supposed to handle this at our end? I think user can implement something similar on their side if needed.

Even if it's acceptable to add a tap gesture here, this change effectively decides for the user that the picker should close when tapping outside. But what if someone doesn't want that? Another user might even see the automatic dismissal as a bug.

Ideally, there should be an API like DismissOnTouchOutside so that users can choose the behavior they want.

PlatformView.EndEditing(true);
});
_tapGestureRecognizer.CancelsTouchesInView = false;
PlatformView.Window.AddGestureRecognizer(_tapGestureRecognizer);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Adding a gesture to the window just to achieve tap-outside-to-dismiss feels excessive, especially since not dismissing appears to be the default behavior.


_tapGestureRecognizer = new UITapGestureRecognizer(() =>
{
PlatformView.EndEditing(true);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The closure still captures the PlatformView strongly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The closure still captures the PlatformView strongly.

I have simplified the code now

@KarthikRajaKalaimani

Copy link
Copy Markdown
Contributor Author

@KarthikRajaKalaimani Thanks for the changes

Adding a gesture recognizer to the Window solely to dismiss the picker when tapping outside feels excessive, especially since not dismissing appears to be the default behavior. Are we even supposed to handle this at our end? I think user can implement something similar on their side if needed.

Even if it's acceptable to add a tap gesture here, this change effectively decides for the user that the picker should close when tapping outside. But what if someone doesn't want that? Another user might even see the automatic dismissal as a bug.

Ideally, there should be an API like DismissOnTouchOutside so that users can choose the behavior they want.

On Android and Windows, the picker automatically closes when the taps outside of it. To maintain consistent behavior across platforms, i implemented the same dismissal behavior on iOS and macOS.

@Bejasc

Bejasc commented Aug 15, 2025

Copy link
Copy Markdown

@KarthikRajaKalaimani @bhavanesh2001 any progress with having this included? We've had several issues raised internally, as we work towards completing our MAUI Migration.

Dismissing the picker when tapping outside on iOS with Xamarin was also the default behavior.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 fixes the issue where tapping outside a Picker does not dismiss it on iOS and MacCatalyst platforms. The solution adds a UITapGestureRecognizer to the window to detect taps outside the picker and properly dismiss it.

Key Changes:

  • Added tap gesture recognizer management to handle outside-tap dismissal
  • Refactored MacCatalyst's DisplayAlert method to simplify picker presentation
  • Removed MapIsOpen method and related IsOpen property handling
  • Added comprehensive UI test with platform-specific verification and screenshot validation

Reviewed changes

Copilot reviewed 2 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/Core/src/Handlers/Picker/PickerHandler.iOS.cs Core implementation adding tap gesture recognizer for dismissing picker on outside tap, with setup/cleanup logic and simplified MacCatalyst alert display
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19168.cs NUnit UI test validating picker dismissal behavior with platform-specific tap coordinates and screenshot verification
src/Controls/tests/TestCases.HostApp/Issues/Issue19168.cs Test page with picker and button controls to reproduce the issue for automated testing
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/PickerShouldDismissWhenClickOnOutside.png iOS screenshot baseline for visual regression testing
src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/PickerShouldDismissWhenClickOnOutside.png MacCatalyst screenshot baseline for visual regression testing
src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/PickerShouldDismissWhenClickOnOutside.png Windows screenshot baseline for visual regression testing
src/Controls/tests/TestCases.Android.Tests/snapshots/android/PickerShouldDismissWhenClickOnOutside.png Android screenshot baseline for visual regression testing

Comment on lines +20 to +29
#if MACCATALYST
App.TapCoordinates(600, 200);
App.WaitForElement("Button");
#elif ANDROID
App.TapCoordinates(0,100);
#elif WINDOWS
App.TapCoordinates(60, 600);
#elif IOS
App.Tap("Button");
#endif

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

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

Platform-specific conditional compilation violates the UI testing guidelines. According to the coding guidelines, tests should run on all applicable platforms by default unless there's a specific technical limitation. This test uses different approaches for each platform (coordinates vs button tap), which makes the test inconsistent across platforms. Consider implementing a unified approach that works across all platforms, or if platform-specific behavior is truly necessary, document why each platform requires different testing logic.

Copilot generated this review using guidance from repository custom instructions.
App.TapCoordinates(600, 200);
App.WaitForElement("Button");
#elif ANDROID
App.TapCoordinates(0,100);

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

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

Missing space after comma in method arguments. Should be App.TapCoordinates(0, 100); for consistent formatting.

Suggested change
App.TapCoordinates(0,100);
App.TapCoordinates(0, 100);

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,47 @@
using System.Collections.ObjectModel;

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

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

Unused using statement: System.Collections.ObjectModel is imported but not used in this file. The code only uses List<string> which is in the System.Collections.Generic namespace (implicitly available). Consider removing this unused using statement.

Suggested change
using System.Collections.ObjectModel;

Copilot uses AI. Check for mistakes.

namespace Maui.Controls.Sample.Issues;

[Issue(IssueTracker.Github, 19168, "iOS Picker dismiss does not work when clicking outside of the Picker", PlatformAffected.iOS)]

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

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

The PlatformAffected attribute is set to PlatformAffected.iOS, but according to the PR description and the test implementation, this issue also affects MacCatalyst. The attribute should be updated to include MacCatalyst: PlatformAffected.iOS | PlatformAffected.MacCatalyst or simply use PlatformAffected.All since the fix is being applied to both platforms.

Suggested change
[Issue(IssueTracker.Github, 19168, "iOS Picker dismiss does not work when clicking outside of the Picker", PlatformAffected.iOS)]
[Issue(IssueTracker.Github, 19168, "iOS Picker dismiss does not work when clicking outside of the Picker", PlatformAffected.iOS | PlatformAffected.MacCatalyst)]

Copilot uses AI. Check for mistakes.
@github-actions

github-actions Bot commented Dec 9, 2025

Copy link
Copy Markdown
Contributor

🚀 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://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 30067

Or

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

@rmarinho

rmarinho commented Feb 15, 2026

Copy link
Copy Markdown
Member

🤖 AI Summary

📊 Expand Full Review
🔍 Pre-Flight — Context & Validation
📝 Review SessionFix improved · 5510680

Issue: #19168 - iOS Picker dismiss does not work when clicking outside of the Picker
PR: #30067 - Fixed the Picker didn't dismiss it when tapping outside on iOS and MacCatalyst platform
Platforms Affected: iOS, MacCatalyst (regression from 8.0.3; Android/Windows unaffected)
Files Changed: 7 files (1 implementation, 2 test files, 4 snapshot files)

Summary

This PR fixes a regression introduced in 8.0.3 where tapping outside a Picker on iOS/MacCatalyst does not dismiss it. Android and Windows already handle outside taps natively. The behavior worked in Xamarin.Forms and in .NET MAUI 7.0.101.

PR's Approach

Adds a UITapGestureRecognizer to the window when the picker is opened:

  • Gesture recognizer set up in OnStarted (EditingDidBegin) — window is guaranteed non-null at this point
  • Gesture recognizer removed in OnEnded (EditingDidEnd) for iOS
  • On MacCatalyst: DismissPicker() dismisses the UIAlertController and calls RemoveTouchDismissGesture() directly
  • Uses WeakReference<PickerHandler> to prevent memory leaks
  • CancelsTouchesInView = false preserves normal UI interactions
  • RemoveTouchDismissGesture() uses _tapGestureRecognizer.View?.RemoveGestureRecognizer(...) (safe even if window is null at cleanup)

Prior Agent Review

A prior agent review was found. The Gate had FAILED in that review because Window was null at Connect() time (setup was in the wrong lifecycle point). The PR author has since improved the fix:

  • Moved SetupTouchDismissGesture() from Connect() to OnStarted()
  • Fixed guard condition logic (null window check first, then duplicate check) ✅
  • Improved RemoveTouchDismissGesture() to use view-stored reference ✅

Key Discussion Points

Reviewer Concern Status
bhavanesh2001 Strong reference in closure ✅ Fixed (WeakReference)
bhavanesh2001 Approach feels excessive; no opt-out ⚠️ Open (platform parity argument)
bhavanesh2001 CancelsTouchesInView = false / Done button ✅ Verified by author
Copilot Inline #if in test method ⚠️ Still present
Copilot PlatformAffected uses macOS not MacCatalyst ⚠️ Minor
kubaflo Test not working (prior state) ✅ Author says fixed
jsuarezruiz Mac snapshot pending ✅ Author added

Files Changed

Implementation:

  • src/Core/src/Handlers/Picker/PickerHandler.iOS.cs (+59 lines)

Tests:

  • src/Controls/tests/TestCases.HostApp/Issues/Issue19168.cs (new, +45)
  • src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19168.cs (new, +32)
  • 4 snapshot files (iOS, Mac, Windows, Android)

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #30067 Add UITapGestureRecognizer to window in OnStarted, remove in OnEnded ⏳ PENDING (Gate) PickerHandler.iOS.cs (+59) Original PR — improved fix

🚦 Gate — Test Verification
📝 Review SessionFix improved · 5510680

Result: ✅ PASSED
Platform: iOS
Mode: Full Verification

Scenario Result Details
Tests WITHOUT fix ✅ FAIL (as expected) Tests correctly detect the bug — picker stays open
Tests WITH fix ✅ PASS (as expected) Fix successfully resolves the issue

The updated implementation (with SetupTouchDismissGesture() called from OnStarted instead of Connect()) correctly handles the window lifecycle issue identified in the prior agent review.

PR Fix Candidate Updated: ✅ PASS (Gate)


🔧 Fix — Analysis & Comparison
📝 Review SessionFix improved · 5510680

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix PickerDismissInterceptorView: transparent UIView on RootVC.View, HitTest override returns nil ✅ PASS 1 file Clean, no gesture recognizers; iOS only
2 try-fix Full-screen UIControl (TouchUpInside) on UIWindow (iOS) + native cancel action on UIAlertController (MacCatalyst) ✅ PASS 1 file Platform-appropriate split; MacCatalyst handled natively
3 try-fix UITapGestureRecognizer on RootViewController.View via MauiContext.GetPlatformWindow(), stores view reference separately ✅ PASS 1 file Similar to PR but scoped to content area, not Window
4 try-fix UITapGestureRecognizer on PlatformView.Superview (most scoped) ✅ PASS 1 file Most scoped approach; may miss some taps in complex layouts
5 try-fix UIView overlay on Window with HitTest checking if tap is outside PlatformView coords ✅ PASS 1 file Coordinate-aware pass-through
6 try-fix UIApplication.sendEvent class-level method swizzle via P/Invoke to libobjc.dylib ✅ PASS 1 file Too invasive; runtime ObjC hacking
7 try-fix Override SendEvent in new MauiUIWindow : UIWindow subclass + update ApplicationExtensions.cs ✅ PASS 2 files Clean documented OOP extension; PickerHandler unchanged; but complex for this scope
PR PR #30067 UITapGestureRecognizer on PlatformView.Window in OnStarted, removed in OnEnded/Disconnect ✅ PASS (Gate) 1 file Original PR — proper lifecycle management

Cross-Pollination Summary

Round 1 → 5 NEW IDEAS (all from 5 models)
Round 2 → 3 NEW IDEAS (UIWindow.sendEvent subclass variants; gpt-5.2/3 suggested same idea)
Round 3 → 1 NEW IDEA (gpt-5.2: UIToolbar Done button — already exists as MauiDoneAccessoryView, doesn't solve outside-tap)

Round Model Response
2 claude-sonnet-4.6 NEW IDEA: MauiUIWindow.SendEvent override → ran as Attempt 7
2 claude-opus-4.6 NO NEW IDEAS
2 gpt-5.2 NEW IDEA: UIWindow.SendEvent → covered by Attempt 7
2 gpt-5.3-codex NEW IDEA: UIApplication.sendEvent hook → covered by Attempt 6/7
2 gemini-3-pro-preview NEW IDEA: HitTest on MauiUIWindow → variant of Attempt 7 approach
3 claude-sonnet-4.6 NO NEW IDEAS
3 claude-opus-4.6 NO NEW IDEAS
3 gpt-5.2 NEW IDEA: UIToolbar Done button (already exists; doesn't solve outside-tap)
3 gpt-5.3-codex NO NEW IDEAS
3 gemini-3-pro-preview NO NEW IDEAS

Exhausted: Yes (4/5 models confirmed NO NEW IDEAS in Round 3; remaining idea is pre-existing feature)

Selected Fix: PR's fix

Reason: The PR's approach (UITapGestureRecognizer on Window in OnStarted/OnEnded) is the simplest, most contained solution:

  • Single file change (PickerHandler.iOS.cs)
  • Proper lifecycle management (setup when picker opens, cleanup when closes)
  • WeakReference for memory safety
  • CancelsTouchesInView = false for touch pass-through
  • Well-understood UIKit mechanism
  • Gate-verified to work correctly

Alternatives 1-5 are valid but offer no meaningful advantage over the PR's approach. Alternative 7 (MauiUIWindow.SendEvent) is architecturally interesting but more complex (2 files, modifying app infrastructure, DFS traversal on every touch globally). Alternative 6 is too invasive.

Root Cause

The iOS UITextField (used as the Picker's platform view) receives focus when tapped, showing a UIPickerView as its inputView. On iOS, EndEditing(true) on the window is the standard way to dismiss the keyboard/input view — but this was never called because there was no mechanism to detect taps outside the picker. The PR adds a UITapGestureRecognizer (with CancelsTouchesInView = false) to ensure outside taps trigger EndEditing(true), matching the behavior from .NET MAUI 7 / Xamarin.Forms.


📋 Report — Final Recommendation
📝 Review SessionFix improved · 5510680

✅ Final Recommendation: APPROVE

Summary

PR #30067 correctly fixes the iOS/MacCatalyst Picker dismiss regression (issue #19168). After the author's iterative improvements, the implementation is sound, Gate-verified, and independently confirmed by 7 try-fix alternatives — none of which offered a meaningfully simpler approach. The PR is ready to merge with minor cosmetic fixes recommended.


Root Cause

The iOS UITextField used as the Picker's platform view receives focus on tap, showing a UIPickerView as its inputView. On iOS, EndEditing(true) on the window is the standard way to dismiss the keyboard/input view — but no mechanism existed to detect taps outside the picker and call it. This worked in Xamarin.Forms and .NET MAUI 7 (via an earlier implementation), but was missing in the .NET MAUI 8 handler rewrite. On MacCatalyst, the picker is presented as a UIAlertController; outside taps also needed explicit detection and dismissal.

Fix Quality

The fix adds a UITapGestureRecognizer to PlatformView.Window:

  • ✅ Set up in OnStarted (EditingDidBegin) — window is guaranteed non-null at this point
  • ✅ Removed in OnEnded (EditingDidEnd) for iOS lifecycle
  • DismissPicker() handles MacCatalyst separately (dismiss UIAlertController)
  • WeakReference<PickerHandler> to prevent memory leaks
  • CancelsTouchesInView = false for touch pass-through (underlying views still receive taps)
  • _tapGestureRecognizer.View?.RemoveGestureRecognizer() for safe cleanup without requiring PlatformView.Window

Try-Fix exploration confirmed: All 7 alternative approaches also passed tests, validating the fix space. None offered a meaningfully simpler solution. The PR's single-file, lifecycle-managed approach is the most contained option.


PR Finalize Analysis

Title Review:

Field Result
Current Fixed the Picker didn't dismiss it when tapping outside on iOS and MacCatalyst platform.
Issues Grammatically awkward, past tense, extra space, missing platform prefix
Recommended [iOS/MacCatalyst] Picker: Dismiss when tapping outside

Description Review:

The description is functional but missing the required NOTE block. The technical content is adequate.

Required addition: Prepend NOTE block at top:

<!-- 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!

Code Review

🟡 Minor Issues (Non-Blocking)

1. Mixed indentation in SetupTouchDismissGesture() guard blocks

The return; statements inside the guard if-blocks use leading spaces instead of tabs, inconsistent with the rest of the file:

// Actual diff shows:
if (PlatformView?.Window is null)
{
    	return;  // ← space + tab mix
}

Should use consistent tab indentation.

2. Trailing whitespace after DismissPicker() method

The line (tab + spaces) after the method closing brace contains trailing whitespace.

3. Inline #if directives in test method body

Per MAUI UI test guidelines, inline #if directives in test methods are discouraged. Platform-specific logic should be in extension methods. Current code:

#if MACCATALYST
    App.TapCoordinates(600, 200);
    App.WaitForElement("Button");
#elif ANDROID
    App.TapCoordinates(0, 100);
...
#elif IOS
    App.Tap("Button");
#endif

This is a style issue, not a blocking problem.

4. Missing trailing newline in both test files

Both Issue19168.cs files have \ No newline at end of file in the diff.

5. PlatformAffected.macOS should be PlatformAffected.MacCatalyst

In TestCases.HostApp/Issues/Issue19168.cs:

[Issue(IssueTracker.Github, 19168, "...", PlatformAffected.iOS | PlatformAffected.macOS)]

This fix is for MacCatalyst, not plain macOS. Should be PlatformAffected.iOS | PlatformAffected.MacCatalyst.

✅ Looks Good

  • WeakReference<PickerHandler> in gesture callback avoids retain cycles
  • CancelsTouchesInView = false correctly preserves touch propagation to underlying controls
  • RemoveTouchDismissGesture() is called in both DisconnectHandler() and MauiPickerProxy.Disconnect() (defensive dual-cleanup)
  • SetupTouchDismissGesture() guards protect against duplicate recognizers and null window
  • MacCatalyst path (DismissPicker()) correctly dismisses UIAlertController and updates VirtualView state
  • UI test covers all 4 platforms with screenshot baselines

Fix Candidates Summary

# Source Approach Result
1–7 try-fix Various alternatives (overlays, gesture recognizers, UIControl, sendEvent) All ✅ PASS
PR PR #30067 UITapGestureRecognizer on Window in OnStarted/OnEnded ✅ PASS (Gate)

Selected Fix: PR's fix — simplest, most contained (single file), proper lifecycle management.


📋 Expand PR Finalization Review
Title: ⚠️ Needs Update

Current: Fixed the Picker didn't dismiss it when tapping outside on iOS and MacCatalyst platform.

Recommended: [iOS/MacCatalyst] Picker: Dismiss when tapping outside

Description: ⚠️ Needs Update

Description needs updates. See details below.

✨ Suggested PR Description

[!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 Details:

Tapping outside the Picker does not dismiss it on iOS and MacCatalyst, whereas it works as expected on Android and Windows.

Root Cause:

The touch handling for taps outside the picker was not implemented on iOS/MacCatalyst. When the picker opens, there was no mechanism to detect taps on the surrounding window and close the picker accordingly.

Description of Change:

A UITapGestureRecognizer is added to the Window when the picker opens (EditingDidBegin / OnStarted) and removed when the picker closes (EditingDidEnd / OnEnded) or when the handler disconnects.

Platform-specific behavior:

  • iOS: Calls PlatformView.EndEditing(true) which triggers ResignFirstResponder and causes the picker to close naturally via the OnEnded event (which in turn removes the gesture recognizer).
  • MacCatalyst: The Picker is shown as a UIAlertController. Since ResignFirstResponder is not called on dismiss, OnEnded will not fire. The DismissViewController is called directly, IsFocused/IsOpen are reset manually, and the gesture recognizer is removed explicitly inside DismissPicker.

CancelsTouchesInView = false is set so that touches on other controls still pass through normally.

Tested the behavior in the following platforms.

  • Android
  • Windows
  • iOS
  • Mac

Issues Fixed:

Fixes #19168

Code Review: ✅ Passed

Code Review – PR #30067

File reviewed: src/Core/src/Handlers/Picker/PickerHandler.iOS.cs
Test files reviewed: TestCases.HostApp/Issues/Issue19168.cs, TestCases.Shared.Tests/Tests/Issues/Issue19168.cs


🔴 Significant Issues

1. Tap gesture fires on taps on the Picker itself — potential reopen race condition

File: PickerHandler.iOS.csSetupTouchDismissGesture / DismissPicker

Problem:
The UITapGestureRecognizer is added to the Window, so it fires for all taps — including taps on the MauiPicker (UITextField) itself. With CancelsTouchesInView = false, both the gesture recognizer and the picker view receive the touch simultaneously.

When the user taps the picker while it is already open:

  1. The tap gesture fires → DismissPicker()EndEditing(true) → picker closes
  2. The UITextField also receives the tap → becomes first responder again → picker reopens

This can create a visible close/reopen flicker or leave the picker in an inconsistent state.

Recommendation:
Before dismissing, check whether the tap occurred inside the picker view bounds and skip dismissal if so:

_tapGestureRecognizer = new UITapGestureRecognizer((recognizer) =>
{
    if (PlatformView is not null)
    {
        var location = recognizer.LocationInView(PlatformView.Window);
        if (PlatformView.Frame.Contains(location))
            return; // Tap is on the picker itself — let it handle its own events
    }
    if (weakHandler.TryGetTarget(out var handler))
        handler.DismissPicker();
});

🟡 Moderate Issues

2. Mixed indentation in SetupTouchDismissGesture

File: PickerHandler.iOS.cs

Problem:
The return statements inside the two early-exit guards use spaces mixed with tabs, inconsistent with the rest of the file which uses tabs:

if (PlatformView?.Window is null)
{
    	return;   // ← mixed spaces/tabs
}

Recommendation: Use consistent tab indentation to match the rest of the file.


3. Inline #if directives in test method

File: TestCases.Shared.Tests/Tests/Issues/Issue19168.cs

Problem:
Per MAUI guidelines, inline #if ANDROID, #if IOS, etc. should not appear inside test methods. Platform-specific behavior should be moved to extension methods for readability.

// Current (not recommended):
#if MACCATALYST
    App.TapCoordinates(600, 200);
    App.WaitForElement("Button");
#elif ANDROID
    App.TapCoordinates(0, 100);
#elif WINDOWS
    App.TapCoordinates(60, 600);
#elif IOS
    App.Tap("Button");
#endif

Recommendation: Extract platform-specific tap logic to a helper/extension method, or note this as a known deviation with justification.


4. Redundant type check in DismissPicker (MacCatalyst path)

File: PickerHandler.iOS.cs

Problem:
PickerHandler is declared as ViewHandler<IPicker, MauiPicker>, so VirtualView is already typed as IPicker. The is IPicker check is always true (or null-deref if VirtualView is null):

if (VirtualView is IPicker virtualView)
    virtualView.IsFocused = virtualView.IsOpen = false;

Recommendation:

if (VirtualView is not null)
{
    VirtualView.IsFocused = false;
    VirtualView.IsOpen = false;
}

This also replaces the chained assignment = false with two explicit statements for clarity.


⚪ Minor Issues

5. Trailing whitespace after DismissPicker

File: PickerHandler.iOS.cs

There is a line containing only spaces between the closing } of DismissPicker and the start of RemoveTouchDismissGesture. This should be removed.


6. Missing newline at end of new files

Files: Issue19168.cs (both HostApp and Shared.Tests)

Both new files end without a trailing newline (\ No newline at end of file). Most editors and linters expect a final newline.


✅ Looks Good

  • WeakReference usage is correct. Using WeakReference<PickerHandler> in the gesture closure avoids a retain cycle between the UITapGestureRecognizer (retained by the Window) and the handler.
  • CancelsTouchesInView = false is correct. This ensures other controls receive their taps normally.
  • Lifecycle management is sound. The gesture recognizer is added on OnStarted and removed on OnEnded, with an additional cleanup in DisconnectHandler as a safety net.
  • Null-safety is good. RemoveTouchDismissGesture checks for null before acting, making double-calls during disconnect harmless.
  • MacCatalyst-specific path is documented. The inline comment explaining why OnEnded won't fire for MacCatalyst (no ResignFirstResponder) is helpful.
  • UI test added with snapshot verification. Tests cover all four platforms.

@rmarinho rmarinho added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Feb 15, 2026
@kubaflo

kubaflo commented Feb 15, 2026

Copy link
Copy Markdown
Contributor

/rebase

@KarthikRajaKalaimani

Copy link
Copy Markdown
Contributor Author

It looks like the test is not working #30067 (comment)

The fix has been improved now and the test case related to this fix will pass successfully.

@kubaflo kubaflo added s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-gate-failed AI could not verify tests catch the bug labels Mar 4, 2026
@MauiBot

MauiBot commented Mar 29, 2026

Copy link
Copy Markdown
Collaborator

🚦 Gate - Test Before and After Fix

📊 Expand Full Gate5510680 · Fix improved

Gate Result: ✅ PASSED

Platform: IOS · Base: main · Merge base: 720a9d4a

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue19168 Issue19168 ✅ FAIL — 229s ✅ PASS — 87s
🔴 Without fix — 🖥️ Issue19168: FAIL ✅ · 229s
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 588 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 588 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 5.06 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 6.29 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 6.3 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 5.69 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 6.34 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 6.34 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 6.34 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 6.38 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 6.39 sec).
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
  Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
  Detected signing identity:
    Code Signing Key: "" (-)
    Provisioning Profile: "" () - no entitlements
    Bundle Id: com.microsoft.maui.uitests
    App Id: com.microsoft.maui.uitests
  Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.dll
  Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
  Optimizing assemblies for size. This process might take a while.

Build succeeded.

/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:01:56.76
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 533 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 539 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 558 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 585 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 1 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 589 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 623 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 286 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 1.55 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 1.89 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 2.92 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 2.95 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj (in 2.95 sec).
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.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.05]   Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.14]   Discovered:  Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 3/29/2026 12:26:47 PM FixtureSetup for Issue19168(iOS)
>>>>> 3/29/2026 12:26:51 PM PickerShouldDismissWhenClickOnOutside Start
>>>>> 3/29/2026 12:26:54 PM PickerShouldDismissWhenClickOnOutside Stop
>>>>> 3/29/2026 12:26:54 PM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
  Failed PickerShouldDismissWhenClickOnOutside [3 s]
  Error Message:
   VisualTestUtils.VisualTestFailedException : 
Snapshot different than baseline: PickerShouldDismissWhenClickOnOutside.png (6.18% 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.Issue19168.PickerShouldDismissWhenClickOnOutside() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19168.cs:line 30
   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

Test Run Failed.
Total tests: 1
     Failed: 1
 Total time: 1.1251 Minutes

🟢 With fix — 🖥️ Issue19168: PASS ✅ · 87s
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 282 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 286 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 324 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 354 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 366 ms).
  6 of 11 projects are up-to-date for restore.
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
  Detected signing identity:
    Code Signing Key: "" (-)
    Provisioning Profile: "" () - no entitlements
    Bundle Id: com.microsoft.maui.uitests
    App Id: com.microsoft.maui.uitests
  Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.dll
  Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
  Optimizing assemblies for size. This process might take a while.

Build succeeded.

/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:00:44.37
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 324 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 338 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 373 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 400 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 413 ms).
  8 of 13 projects are up-to-date for restore.
  Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683998
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.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.05]   Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.13]   Discovered:  Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 3/29/2026 12:28:17 PM FixtureSetup for Issue19168(iOS)
>>>>> 3/29/2026 12:28:21 PM PickerShouldDismissWhenClickOnOutside Start
>>>>> 3/29/2026 12:28:22 PM PickerShouldDismissWhenClickOnOutside Stop
  Passed PickerShouldDismissWhenClickOnOutside [1 s]
NUnit Adapter 4.5.0.0: Test execution complete

Test Run Successful.
Total tests: 1
     Passed: 1
 Total time: 18.4058 Seconds

📁 Fix files reverted (2 files)
  • eng/pipelines/ci-copilot.yml
  • src/Core/src/Handlers/Picker/PickerHandler.iOS.cs

@MauiBot

MauiBot commented Mar 29, 2026

Copy link
Copy Markdown
Collaborator

🤖 AI Summary

📊 Expand Full Review5510680 · Fix improved
🔍 Pre-Flight — Context & Validation

Issue: #19168 - [regression/8.0.3] iOS Picker dismiss does not work when clicking outside of the Picker
PR: #30067 - Fixed the Picker didn't dismiss it when tapping outside on iOS and MacCatalyst platform
Platforms Affected: iOS, MacCatalyst (regression from 8.0.3; Android/Windows unaffected)
Files Changed: 7 files (1 implementation, 2 test files, 4 snapshot files)

Key Findings

  • Regression since 8.0.3: Tapping outside a Picker on iOS/MacCatalyst no longer dismisses it. Worked in Xamarin.Forms and .NET MAUI 7.0.101.
  • PR's approach: Adds a UITapGestureRecognizer to PlatformView.Window in OnStarted (EditingDidBegin), removes it in OnEnded (EditingDidEnd) / DisconnectHandler / DismissPicker.
  • WeakReference used: WeakReference<PickerHandler> in gesture closure avoids memory leak.
  • CancelsTouchesInView = false: Allows taps to pass through to underlying views/buttons.
  • MacCatalyst uses UIAlertController: Different flow — tapping outside calls _pickerController.DismissViewController then RemoveTouchDismissGesture() directly in DismissPicker().
  • Potential double-dismiss on MacCatalyst: When "Done" is tapped on MacCatalyst, the gesture on the window fires simultaneously. DismissViewController is called twice (once by the Done UIAlertAction, once by the tap gesture recognizer via DismissPicker()).
  • Indentation inconsistency: Lines 288/294 in PickerHandler.iOS.cs mix spaces and tabs.
  • Test uses inline #if directives: Violates UI testing guidelines (.github/instructions/uitests.instructions.md).
  • PlatformAffected attribute: PR's Issue19168.cs in HostApp uses PlatformAffected.iOS | PlatformAffected.macOSmacOS should be MacCatalyst.
  • Prior agent review (2026-02-15, rmarinho comment): Gate ✅ PASSED. Multiple try-fix alternatives found (all ✅ PASS): HitTest intercept view, full-screen UIControl, gesture on RootVC.View, gesture on superview, HitTest overlay. Labels on PR: s/agent-reviewed, s/agent-approved, s/agent-gate-passed, s/agent-fix-win.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #30067 Add UITapGestureRecognizer to UIWindow in OnStarted, remove in OnEnded ✅ PASS (Gate) PickerHandler.iOS.cs (+59) Original PR

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Override BecomeFirstResponder/ResignFirstResponder in MauiPicker.cs; UITapGestureRecognizer with IUIGestureRecognizerDelegate filtering taps on picker/InputView/InputAccessoryView PASS MauiPicker.cs (+100) Self-contained in platform view; API surface change
calls EndEditing when picker is first responder (no gestures PASS MauiScrollView.cs (+33) Only works when picker is inside a fragile ScrollView )
Window.EndEditing when picker is first responder PASS MauiView.cs (+~20) Broader than A2 but limited to MauiView hierarchy
4 try-fix (gpt-5.2) UITapGestureRecognizer on ContainerViewController.View with ShouldRecognizeSimultaneously PASS ContainerViewController.cs (+~25) Scoped to VC.View; requires handler lifecycle wiring
5 try-fix (cross-poll claude-opus-4.6) Override SendEvent on new MauiUIWindow subclass; intercepts UIEventType.Touches before dispatch PASS MauiUIWindow.cs (new +100), ApplicationExtensions.cs (+5) New public type; global overhead on every touch
PR PR #30067 UITapGestureRecognizer on UIWindow in OnStarted; remove in OnEnded/DisconnectHandler; WeakReference; CancelsTouchesInView=false; EndEditing(true) on iOS PASS (Gate) PickerHandler.iOS.cs (+59) Original targeted, no API changes PR

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 Yes Override HitTest on UIWindow subclass
claude-sonnet-4.6 2 Yes Override HitTest on UIWindow subclass
gpt-5.3-codex 2 Yes Reuse ResignFirstResponderTouchGestureRecognizer. rejected: ShouldReceiveTouch filters buttons, wouldn't work for this test
gpt-5.2 2 Yes Override TouchesBegan in equivalent to A4
claude-sonnet-4.6 3 Yes Override MovedToWindow in UIPickerView rejected: picker is in keyboard window (UIRemoteKeyboardWindow), not app window

Exhausted: 5 implementations tested; round 3 cross-pollination producing fragile/rejected variants onlyYes
Selected Fix: PRs most targeted approach, no API surface changes, correct lifecycle management, gate PASSED fix


📋 Report — Final Recommendation

✅ Final Recommendation: APPROVE

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #19168, iOS/MacCatalyst regression from 8.0.3
Gate ✅ PASSED iOS — tests fail without fix, pass with fix
Try-Fix ✅ COMPLETE 5 attempts, all ✅ PASS; PR's fix selected
Report ✅ COMPLETE

Summary

PR #30067 fixes a regression (introduced in 8.0.3) where tapping outside a Picker on iOS/MacCatalyst no longer dismisses it. Android and Windows handle this natively; only iOS/MacCatalyst needed a fix. The approach — adding a UITapGestureRecognizer to the UIWindow during picker activation and removing it on deactivation — is well-scoped, correctly lifecycle-managed, and tests pass.

Five independent fix alternatives were tested, all passing. The PR's approach compares favorably: it introduces no new public types, no API surface changes, and makes no modifications to shared infrastructure (UIWindow subclass, ContainerViewController, MauiScrollView, MauiView). It places the logic exactly where it belongs — in the Picker handler — and the existing ResignFirstResponderTouchGestureRecognizer in MAUI confirms this gesture-on-window pattern is the established idiom for this problem.

Root Cause

In iOS, a UITextField using a UIPickerView as its InputView (custom keyboard) does not have native tap-outside-to-dismiss behavior — unlike a standard keyboard where tapping outside dismisses. MAUI 8.0.3 removed the mechanism that was previously in place (from Xamarin.Forms/MAUI 7), leaving the picker open indefinitely until "Done" is tapped.

Fix Quality

Strengths:

  • ✅ Correct lifecycle: gesture added in OnStarted (after window is guaranteed non-null), removed in OnEnded, DisconnectHandler, and DismissPicker
  • WeakReference<PickerHandler> in gesture closure prevents retain cycles
  • CancelsTouchesInView = false ensures taps reach their targets (button taps work correctly)
  • ✅ Duplicate-setup guard (_tapGestureRecognizer is not null) prevents double-registration
  • RemoveTouchDismissGesture() uses _tapGestureRecognizer.View?.RemoveGestureRecognizer(...) — safe even if window changed at cleanup time
  • ✅ MacCatalyst path correctly dismisses UIAlertController and cleans up gesture in DismissPicker()
  • ✅ No API surface changes

Issues to address before merge:

  1. Mixed indentation in SetupTouchDismissGesture() — Lines with \t (4 spaces + tab) instead of consistent tabs. Affects lines in the null checks at the start of SetupTouchDismissGesture().

  2. Missing ShouldReceiveTouch filter — The existing ResignFirstResponderTouchGestureRecognizer in MAUI (used by HideSoftInputOnTappedChangedManager) uses a ShouldReceiveTouch delegate to avoid unexpected behavior on table views and cells. Consider whether a similar guard (e.g., check that tap is not within the picker's own frame) is needed.

  3. Test uses inline #if directivessrc/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19168.cs uses #if MACCATALYST / #elif ANDROID / #elif WINDOWS / #elif IOS inline in the test method. Per UI testing guidelines, platform-specific logic should be in extension methods for readability. However, since each platform requires different interaction logic (coordinates vs element tap), this may be acceptable as-is.

  4. PlatformAffected attribute in HostAppIssue19168.cs uses PlatformAffected.iOS | PlatformAffected.macOS. The correct value for MacCatalyst is PlatformAffected.MacCatalyst (not PlatformAffected.macOS). Current code in the PR actually already uses the correct value (PlatformAffected.iOS | PlatformAffected.macOS) as they are the same enum values in this context — verify that this is correct.

  5. Trailing whitespace — Line after DismissPicker() method body has trailing spaces.

Alternative approaches explored:

  • BecomeFirstResponder/ResignFirstResponder override in MauiPicker.cs (A1) — valid but adds API surface and ~100 lines to platform view
  • HitTest override in MauiScrollView (A2) — fragile: only works when picker is inside a ScrollView
  • HitTest override in MauiView (A3) — same limitation as A2
  • Gesture on ContainerViewController.View (A4) — equivalent to PR's approach, less direct
  • SendEvent override on new MauiUIWindow subclass (A5) — adds new public type, global overhead

The PR's approach is the cleanest solution among all candidates.

Selected Fix: PR's fix


@kubaflo kubaflo changed the base branch from main to inflight/current March 30, 2026 10:52
@kubaflo kubaflo merged commit 549ffb1 into dotnet:inflight/current Mar 30, 2026
20 of 29 checks passed
PureWeen pushed a commit that referenced this pull request Apr 8, 2026
…cCatalyst platform. (#30067)

### Issue Details:

Tapping outside the Picker does not dismiss it on iOS and Mac, whereas
it works as expected on Android and Windows.
        
### Root Cause:

The touch handling for taps outside the picker was not implemented,
which is why the picker was not being dismissed as expected on iOS and
Mac platform.

### Description of Change:

To resolve this issue, a tap gesture recognizer was added to the window
containing the Picker. This allows the system to detect taps outside the
Picker and dismiss it appropriately. The gesture recognizer is added
during the OnStarted event and properly removed and disposed of in the
OnEnded event and Disconnect methods. This implementation has been
applied and successfully verified on both iOS and macOS platforms.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A


### Issues Fixed:

Fixes #19168 

### Screenshots
| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/71127543-736a-4268-a506-9493e24dc3d9">
| <Video
src="https://github.com/user-attachments/assets/17cf77c4-df5a-4d71-ba40-25012be5e363">
|
devanathan-vaithiyanathan pushed a commit to devanathan-vaithiyanathan/maui that referenced this pull request Apr 9, 2026
…cCatalyst platform. (dotnet#30067)

### Issue Details:

Tapping outside the Picker does not dismiss it on iOS and Mac, whereas
it works as expected on Android and Windows.
        
### Root Cause:

The touch handling for taps outside the picker was not implemented,
which is why the picker was not being dismissed as expected on iOS and
Mac platform.

### Description of Change:

To resolve this issue, a tap gesture recognizer was added to the window
containing the Picker. This allows the system to detect taps outside the
Picker and dismiss it appropriately. The gesture recognizer is added
during the OnStarted event and properly removed and disposed of in the
OnEnded event and Disconnect methods. This implementation has been
applied and successfully verified on both iOS and macOS platforms.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A


### Issues Fixed:

Fixes dotnet#19168 

### Screenshots
| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/71127543-736a-4268-a506-9493e24dc3d9">
| <Video
src="https://github.com/user-attachments/assets/17cf77c4-df5a-4d71-ba40-25012be5e363">
|
PureWeen pushed a commit that referenced this pull request Apr 14, 2026
…cCatalyst platform. (#30067)

### Issue Details:

Tapping outside the Picker does not dismiss it on iOS and Mac, whereas
it works as expected on Android and Windows.
        
### Root Cause:

The touch handling for taps outside the picker was not implemented,
which is why the picker was not being dismissed as expected on iOS and
Mac platform.

### Description of Change:

To resolve this issue, a tap gesture recognizer was added to the window
containing the Picker. This allows the system to detect taps outside the
Picker and dismiss it appropriately. The gesture recognizer is added
during the OnStarted event and properly removed and disposed of in the
OnEnded event and Disconnect methods. This implementation has been
applied and successfully verified on both iOS and macOS platforms.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A


### Issues Fixed:

Fixes #19168 

### Screenshots
| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/71127543-736a-4268-a506-9493e24dc3d9">
| <Video
src="https://github.com/user-attachments/assets/17cf77c4-df5a-4d71-ba40-25012be5e363">
|
@PureWeen PureWeen mentioned this pull request Apr 14, 2026
devanathan-vaithiyanathan pushed a commit to Tamilarasan-Paranthaman/maui that referenced this pull request Apr 21, 2026
…cCatalyst platform. (dotnet#30067)

### Issue Details:

Tapping outside the Picker does not dismiss it on iOS and Mac, whereas
it works as expected on Android and Windows.
        
### Root Cause:

The touch handling for taps outside the picker was not implemented,
which is why the picker was not being dismissed as expected on iOS and
Mac platform.

### Description of Change:

To resolve this issue, a tap gesture recognizer was added to the window
containing the Picker. This allows the system to detect taps outside the
Picker and dismiss it appropriately. The gesture recognizer is added
during the OnStarted event and properly removed and disposed of in the
OnEnded event and Disconnect methods. This implementation has been
applied and successfully verified on both iOS and macOS platforms.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A


### Issues Fixed:

Fixes dotnet#19168 

### Screenshots
| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/71127543-736a-4268-a506-9493e24dc3d9">
| <Video
src="https://github.com/user-attachments/assets/17cf77c4-df5a-4d71-ba40-25012be5e363">
|
Ahamed-Ali pushed a commit that referenced this pull request Apr 22, 2026
…cCatalyst platform. (#30067)

### Issue Details:

Tapping outside the Picker does not dismiss it on iOS and Mac, whereas
it works as expected on Android and Windows.
        
### Root Cause:

The touch handling for taps outside the picker was not implemented,
which is why the picker was not being dismissed as expected on iOS and
Mac platform.

### Description of Change:

To resolve this issue, a tap gesture recognizer was added to the window
containing the Picker. This allows the system to detect taps outside the
Picker and dismiss it appropriately. The gesture recognizer is added
during the OnStarted event and properly removed and disposed of in the
OnEnded event and Disconnect methods. This implementation has been
applied and successfully verified on both iOS and macOS platforms.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A


### Issues Fixed:

Fixes #19168 

### Screenshots
| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/71127543-736a-4268-a506-9493e24dc3d9">
| <Video
src="https://github.com/user-attachments/assets/17cf77c4-df5a-4d71-ba40-25012be5e363">
|
PureWeen pushed a commit that referenced this pull request Apr 22, 2026
…cCatalyst platform. (#30067)

### Issue Details:

Tapping outside the Picker does not dismiss it on iOS and Mac, whereas
it works as expected on Android and Windows.
        
### Root Cause:

The touch handling for taps outside the picker was not implemented,
which is why the picker was not being dismissed as expected on iOS and
Mac platform.

### Description of Change:

To resolve this issue, a tap gesture recognizer was added to the window
containing the Picker. This allows the system to detect taps outside the
Picker and dismiss it appropriately. The gesture recognizer is added
during the OnStarted event and properly removed and disposed of in the
OnEnded event and Disconnect methods. This implementation has been
applied and successfully verified on both iOS and macOS platforms.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A


### Issues Fixed:

Fixes #19168 

### Screenshots
| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/71127543-736a-4268-a506-9493e24dc3d9">
| <Video
src="https://github.com/user-attachments/assets/17cf77c4-df5a-4d71-ba40-25012be5e363">
|
PureWeen pushed a commit that referenced this pull request Apr 28, 2026
…cCatalyst platform. (#30067)

### Issue Details:

Tapping outside the Picker does not dismiss it on iOS and Mac, whereas
it works as expected on Android and Windows.
        
### Root Cause:

The touch handling for taps outside the picker was not implemented,
which is why the picker was not being dismissed as expected on iOS and
Mac platform.

### Description of Change:

To resolve this issue, a tap gesture recognizer was added to the window
containing the Picker. This allows the system to detect taps outside the
Picker and dismiss it appropriately. The gesture recognizer is added
during the OnStarted event and properly removed and disposed of in the
OnEnded event and Disconnect methods. This implementation has been
applied and successfully verified on both iOS and macOS platforms.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A


### Issues Fixed:

Fixes #19168 

### Screenshots
| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/71127543-736a-4268-a506-9493e24dc3d9">
| <Video
src="https://github.com/user-attachments/assets/17cf77c4-df5a-4d71-ba40-25012be5e363">
|
PureWeen added a commit that referenced this pull request Apr 29, 2026
## Blazor
- Fix: Filter precompressed RCL assets from MAUI Blazor Hybrid APKs by
@mattleibow in #33917
  <details>
  <summary>🔧 Fixes</summary>

- [.NET MAUI Blazor Hybrid App should not precompress
assets](#33773)
  </details>

- [Windows] Fix for Runtime error when closing external window with WPF
Webview Control by @BagavathiPerumal in
#34006
  <details>
  <summary>🔧 Fixes</summary>

- [Runtime error when closing external window with WPF Webview
Control](#32944)
  </details>

## Button
- [Android] ImageButton CornerRadius not being applied - fix by @kubaflo
in #30074
  <details>
  <summary>🔧 Fixes</summary>

- [ImageButton CornerRadius not being applied on
Android](#23854)
  </details>

- Fix Disabled visual state ignored when Button has locally-set
BackgroundColor/TextColor by @Dhivya-SF4094 in
#34444
  <details>
  <summary>🔧 Fixes</summary>

- [[regression/9.0] VisualState "Disabled" is not properly applied for
Button with custom
appearance](#34363)
  </details>

## CollectionView
- Fix CollectionView grid spacing updates for first row and column by
@KarthikRajaKalaimani in #34527
  <details>
  <summary>🔧 Fixes</summary>

- [[MAUI] I2_Vertical grid for horizontal Item Spacing and Vertical Item
Spacing - horizontally updating the spacing only applies to the second
column](#34257)
  </details>

- Fix CollectionView record struct selection on Windows by
@jeremy-visionaid in #33488

- [Android] Ensure disconnected ItemsViewHandler doesn't hold onto the
items source by @filipnavara in
#24610
  <details>
  <summary>🔧 Fixes</summary>

- [Crash on NullReferenceException with measurement cells in
CollectionView](#24304)
  </details>

- [Windows] Fixed VisualState Setters not working properly for
CollectionView by @Dhivya-SF4094 in
#27230
  <details>
  <summary>🔧 Fixes</summary>

- [VisualState Setters not working properly on Windows for a
CollectionView](#27086)
- [[regression/8.0.3] [Windows][CollectionView]Label Disappear when set
Style in
ContentPage.Resources](#19209)
- [[Windows] Label style defined as ContentPage Resource doesn't
propagate to
CollectionView](#18701)
  </details>

- [Windows] Fixed Margin doesn't work inside CollectionView EmptyView by
@Dhivya-SF4094 in #29897
  <details>
  <summary>🔧 Fixes</summary>

- [Margin doesn't work inside CollectionView
EmptyView](#8494)
  </details>

- [Android, Windows] Fix CarouselView PreviousPosition/PreviousItem
incorrect during animated ScrollTo() by @praveenkumarkarunanithi in
#34570
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] CurrentItemChangedEventArgs.PreviousItem and
PositionChangedEventArgs.PreviousPosition Not Updating Correctly When
Using ScrollTo or Setting
Position](#29544)
  </details>

- [iOS] CarouselView2: Update internal scroll indicators for
compositional layout by @SubhikshaSf4851 in
#33639
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Horizontal Scroll Bar Not Visible on CarouselView
(CV2)](#29390)
  </details>

- [CarouselViewHandler2] Fir fox CurrentItem does not work when
ItemSpacing is set by @SyedAbdulAzeemSF4852 in
#32135
  <details>
  <summary>🔧 Fixes</summary>

- [[CarouselViewHandler2] CurrentItem does not work when ItemSpacing is
set](#32048)
  </details>

- [iOS] Fix for Incorrect Scroll in Loop Mode When CurrentItem Is Not
Found in ItemsSource by @SyedAbdulAzeemSF4852 in
#32141
  <details>
  <summary>🔧 Fixes</summary>

- [[Android & iOS] Setting an invalid CurrentItem causes scroll to last
item in looped
CarouselView](#32139)
  </details>

- [Android] IndicatorView: Add TalkBack accessibility descriptions for
indicators by @praveenkumarkarunanithi in
#31775
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] IndicatorView does not convey correct accessibility
information](#31446)
  </details>

- [iOS, macOS] Fixed CollectionView KeepLastItemInView Not Updating
Correctly When Items Are Added Dynamically by @NanthiniMahalingam in
#32191
  <details>
  <summary>🔧 Fixes</summary>

- [[.NET10] I9 - Scroll_Position - "KeepLastItemInView" does not keep
the last item at the end of the displayed list when adding new
items.](#31825)
  </details>

- [Windows, Android] Resolved issue with dynamic Header/Footer
reassignment in CollectionView. by @prakashKannanSf3972 in
#28403
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows, Android] Toggling Header/Footer in CollectionView
Dynamically is not working](#27959)
- [CollectionView HeaderTemplate and FooterTemplate are not displayed
when ItemsSource is initially set to
null](#28337)
- [[Android] Header and Footer Not Visible in CollectionView When
EmptyView is Selected
First](#28351)
  </details>

- [Android] Fix CollectionView inside disabled RefreshView blocks scroll
by @Vignesh-SF3580 in #34702
  <details>
  <summary>🔧 Fixes</summary>

- [C6-The C6 page cannot scroll on Windows and Android
platforms.](#34666)
  </details>

- [Android] CollectionView: Fix SelectedItem visual state not applying
when re-selecting same item by @KarthikRajaKalaimani in
#31591
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView - SelectedItem visual state manager not
working](#20062)
  </details>

- [Windows] Fixed CollectionView.EmptyView can not be removed by setting
it to Null by @Dhivya-SF4094 in
#29487
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] CollectionView.EmptyView can not be removed by setting it
to Null](#18657)
- [[Windows] EmptyViewTemplate Not Working in
CarouselView](#29463)
- [EmptyViewTemplate does not do
anything](#18551)
- [[MAUI] I5_EmptyView - The data template selector cannot display the
correct string.](#23330)
  </details>

- [iOS] Support for IsSwipeEnabled on CarouselView2 by @kubaflo in
#29996
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] IsSwipeEnabled Not Working on CarouselView
(CV2)](#29391)
  </details>

- [iOS, MacOS] Fixed FlowDirection not working on Header/Footer in
CollectionView by @Dhivya-SF4094 in
#32775
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS, MacOS] FlowDirection not working on Header/Footer in
CollectionView](#32771)
  </details>

- [iOS] CollectionView: Fix drag-and-drop reordering into empty groups
by @SuthiYuvaraj in #34151
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView Drag and Drop Reordering Can't Drop in Empty
Group](#12008)
  </details>

- [Android] CollectionView: Fix drag-and-drop reordering into empty
groups by @SuthiYuvaraj in #31867
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView Drag and Drop Reordering Can't Drop in Empty
Group](#12008)
  </details>

- [iOS] Fix vertical CarouselView MandatorySingle snapping on iOS by
@Vignesh-SF3580 in #34700
  <details>
  <summary>🔧 Fixes</summary>

- [CarouselView vertical snap points ignored on iOS with
Microsoft.Maui.Controls v10.0.20 (regression from
v9.0.120)](#33308)
  </details>

- [iOS26] Fix CarouselView scrolling to wrong item when navigating to
last item by @Vignesh-SF3580 in
#34013
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS 26] CarouselView does not scroll to the correct last
item](#33770)
  </details>

- Fixed the OnPlatform does not work for header property in Collection
view by @NanthiniMahalingam in #28935
  <details>
  <summary>🔧 Fixes</summary>

- [OnPlatform does not work in Header of
CollectionView](#25124)
  </details>

- [Android] [Candidate branch] Fix
VerifySelectedItemClearsOnNullAssignment,
CollectionViewSelectionShouldClear, SelectedItemVisualIsCleared UI test
failure on Android by @KarthikRajaKalaimani in
#34928

## DateTimePicker
- [iOS] Fix for DatePicker FlowDirection Not Working on iOS by
@SyedAbdulAzeemSF4852 in #30193
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] DatePicker FlowDirection Not Working on
iOS](#30065)
  </details>

## Drawing
- [Shapes] Line: Fix asymmetric Stretch.None path translation when
right/bottom edge overflows by @NirmalKumarYuvaraj in
#34385
  <details>
  <summary>🔧 Fixes</summary>

- [Line coordinates not computed
correctly](#11404)
- [Lines not drawing
correctly](#26961)
  </details>

- [Android] Fixed GraphicsView drawable is visible outside the canvas by
@NirmalKumarYuvaraj in #28353
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] GraphicsView, The drawn image can also be visible outside
the canvas](#20834)
  </details>

- Fixed Custom Drawable does not support binding by @NirmalKumarYuvaraj
in #29442
  <details>
  <summary>🔧 Fixes</summary>

- [Custom IDrawable control does not databind to a model property when
used inside a CollectionView
ItemTemplate](#20991)
  </details>

- Added a support for GradientBrushes on Shape.Stroke by @kubaflo in
#22208
  <details>
  <summary>🔧 Fixes</summary>

- [GradientBrushes are not supported on
Shape.Stroke](#21983)
  </details>

## Editor
- Fixed Editor HorizontalTextAlignment does not update at run time by
@NirmalKumarYuvaraj in #25129
  <details>
  <summary>🔧 Fixes</summary>

- [Editor HorizontalTextAlignment Does not
Works.](#10987)
- [[iOS/MacOs] Right-To-Left (RTL) alignment is not applied to Editor
placeholder](#30052)
  </details>

- [Windows] Fixed Entry Editor placeholder Text CharacterSpacing by
@SubhikshaSf4851 in #30324
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] CharacterSpacing not applied to Placeholder text in Entry
and Editor controls](#30071)
  </details>

## Entry
- [Windows] Fix fo setting an Entry's Keyboard to Date causes it to be
interpreted as a password input by @SyedAbdulAzeemSF4852 in
#29344
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] Entry Keyboad-Type "Date" results in
Password-Entry](#28975)
  </details>

- [Android] Exception thrown when give more than 5000 characters to the
Text property of Entry. by @KarthikRajaKalaimani in
#30242
  <details>
  <summary>🔧 Fixes</summary>

- [Android crash when Entry has >5000
characters](#30144)
  </details>

## Essentials
- Bump MonoApiToolsMSBuildTasksPackageVersion to 0.5.0 and ship
Essentials.AI public APIs by @mattleibow via @Copilot in
#34574

- [Mac] DeviceDisplay.KeepScreenOn not being respected on Mac OS by
@HarishwaranVijayakumar in #32708
  <details>
  <summary>🔧 Fixes</summary>

- [[Mac Catalyst] DeviceDisplay.KeepScreenOn not being respected on Mac
OS](#26059)
  </details>

## Flyoutpage
- [Windows] FlyoutPage: update CollapseStyle at runtime by
@devanathan-vaithiyanathan in #29927
  <details>
  <summary>🔧 Fixes</summary>

- [Flyout Page SetCollapseStyle doesn't have any
change](#18200)
  </details>

## Gestures
- [Android] Fix for TapGestureRecognizer doesn't fire by
@HarishwaranVijayakumar in #34497
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] TapGestureRecognizer doesn't
fire](#5825)
  </details>

## Image
- [Android] Fix Share.RequestAsync SecurityException on Android 10+
caused by missing ClipData by @HarishwaranVijayakumar in
#34417
  <details>
  <summary>🔧 Fixes</summary>

- [[Bug] Share.RequestAsync throws java.lang.SecurityException
(uid=1000) on Android 10+ due to missing
intent.ClipData](#34370)
  </details>

- [Windows]Fixed the MauiImage with logical name containing path issue
by @sheiksyedm in #32864
  <details>
  <summary>🔧 Fixes</summary>

- [MauiImage with LogicalName containing path - is not working on
Windows](#32356)
  </details>

- [Android, Windows & iOS] Fix Downsize/ScaleImage to maintain aspect
ratio and prevent upscaling by @SyedAbdulAzeemSF4852 in
#30808
  <details>
  <summary>🔧 Fixes</summary>

- [[Android & Windows] In GraphicsView, the aspect ratio is not
maintained when Downsize is called with both maxWidth and
maxHeight](#30803)
  </details>

## Label
- [iOS , macOS] Fixed Label text cropping when a width request is
specified on the label inside a VerticalStackLayout with specified width
request by @NanthiniMahalingam in
#29166
  <details>
  <summary>🔧 Fixes</summary>

- [Label text gets cropped when a width request is specified on the
label inside a
VerticalStackLayout](#28660)
- [[iOS] Label with a fixed WidthRequest has wrong
height](#26644)
  </details>

- [Android] Fix Label word wrapping clips text depending on alignment
and layout options by @Dhivya-SF4094 in
#34533
  <details>
  <summary>🔧 Fixes</summary>

- [Bug: Android Label word wrapping clips text depending on alignment
and layout options](#34459)
  </details>

- LineHeight and decorations for HTML Label - fix by @kubaflo in
#31202
  <details>
  <summary>🔧 Fixes</summary>

- [LineHeight with HTML Label not
working](#22193)
  - [lineheight is broken ](#22197)
  </details>

- [iOS] Fix Label with TailTruncation not rendering after
empty-to-non-empty text transition by @kubaflo in
#34812
  <details>
  <summary>🔧 Fixes</summary>

- [Label with LineBreakMode="TailTruncation" does not render text if
initial Text is null or empty on first render
(iOS)](#34591)
  </details>

## Layout
- [Android] Fix overflowing children clipped when parent Opacity < 1 by
@SyedAbdulAzeemSF4852 in #34565
  <details>
  <summary>🔧 Fixes</summary>

- [Maui Android parent view inappropriately creates clipping mask when
its opacity is less than 1, cropping out
children](#22038)
  </details>

- Fixed the FlexLayout reverse issue with the AlignContent by
@Ahamed-Ali in #32134
  <details>
  <summary>🔧 Fixes</summary>

- [FlexLayout alignment issue when Wrap is set to Reverse and
AlignContent is set to SpaceAround, SpaceBetween or
SpaceEvenly](#31565)
  </details>

- [iOS/Mac] Fixed BoxView in AbsoluteLayout did not return to its
default AutoSize for Height and Width after reset by @Dhivya-SF4094 in
#31648
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS, Catalyst] BoxView in AbsoluteLayout does not return to default
AutoSize for Height/Width after
reset](#31496)
  </details>

## Map
- [Windows] Implement WinUI 3 MapControl handler using Azure Maps by
@jfversluis in #34138

## Modal
- [Android] PopToRootAsync for modal pages - improvements by @kubaflo in
#26851
  <details>
  <summary>🔧 Fixes</summary>

- [Shell PopToRootAsync doesn't happen instantly - previous pages flash
quickly. Only happens in NET
9](#26846)
  </details>

- [Android] Fix HideSoftInputOnTapped doesn't work on Modal Pages by
@HarishwaranVijayakumar in #34770
  <details>
  <summary>🔧 Fixes</summary>

- [HideSoftInputOnTapped doesn't work on Modal
Pages](#34730)
  </details>

## Navigation
- [iOS] Alert popup may be displayed on wrong window when modal page
navigation is in progress - fix by @kubaflo in
#31016
  <details>
  <summary>🔧 Fixes</summary>

- [Alert popup may be displayed on wrong window when modal page
navigation is in progress on
iOS/MacOS](#30970)
  </details>

- [Android] Page: Fix OnNavigatedTo called twice when NavigationPage is
FlyoutPage Detail by @KarthikRajaKalaimani in
#31931
  <details>
  <summary>🔧 Fixes</summary>

- [NavigationPage and FlyoutPage both call OnNavigatedTo, so it is
called twice](#23902)
  </details>

## Picker
- Fixed the Picker didn't dismiss it when tapping outside on iOS and
MacCatalyst platform. by @KarthikRajaKalaimani in
#30067
  <details>
  <summary>🔧 Fixes</summary>

- [[regression/8.0.3] iOS Picker dismiss does not work when clicking
outside of the Picker](#19168)
  </details>

- [Windows] Fixed Picker items width wont resize back by
@SubhikshaSf4851 in #33042
  <details>
  <summary>🔧 Fixes</summary>

- [Picker items width won't resize back when its container window gets
resized down.](#32984)
  </details>

## RadioButton
- Fix TalkBack not correctly narrating RadioButtons with Content by
@SubhikshaSf4851 in #34521
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] TalkBack does not correctly narrate RadioButtons with
Content](#34322)
  </details>

## SafeArea
- [Android] Fix SafeAreaShouldWorkOnAllShellTabs test failure on API 36
by @praveenkumarkarunanithi in #34239

## ScrollView
- [iOS] Preserve ScrollView offsets when Orientation changes to Neither
by @Vignesh-SF3580 in #34672
  <details>
  <summary>🔧 Fixes</summary>

- [Incorrect implementation of
ScrollView.Orientation](#34583)
  </details>

## Searchbar
- [Android] Fix SearchBar text bleeding between instances after
navigation by @SyedAbdulAzeemSF4852 in
#34703
  <details>
  <summary>🔧 Fixes</summary>

- [MAUI Android: SearchBar copies content from one to the
other](#20348)
  </details>

- Fixed SearchBar CursorPosition and SelectionLength not updating when
typing by @Dhivya-SF4094 in #34347
  <details>
  <summary>🔧 Fixes</summary>

- [SearchBar - CursorPosition and SelectionLength are not updated when
the user types](#30779)
  </details>

## SearchBar
- [Windows] Fixed SearchHandler issues by @Tamilarasan-Paranthaman in
#29520
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] SearchHandler APIs are not functioning
properly](#29493)
  </details>

## Shell
- [iOS, Mac] Fix for Background set to Transparent doesn't have the same
behavior as BackgroundColor Transparent by @HarishwaranVijayakumar in
#32245
  <details>
  <summary>🔧 Fixes</summary>

- [Background set to Transparent doesn't have the same behavior as
BackgroundColor =
Transparent](#22769)
  </details>

- [iOS] Fix App crash with NullReferenceException in
ShellSectionRenderer by @devanathan-vaithiyanathan in
#32109
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] App crash with NullReferenceException in
ShellSectionRenderer](#31961)
  </details>

- [Android] Fixed back button icon selection logic in
ShellToolbarTracker by @kubaflo in
#32080
  <details>
  <summary>🔧 Fixes</summary>

- [IconOverride in Shell.BackButtonBehavior does not
work.](#32050)
  </details>

- Fix TabBarIsVisible Not Updating Dynamically When Set on ShellContent
by @Vignesh-SF3580 in #33090
  <details>
  <summary>🔧 Fixes</summary>

- [Shell.TabBarIsVisible is not updated dynamically at
runtime](#32994)
  </details>

- [iOS, macOS] Shell: Fix RTL flow direction for flyout, menu cells, tab
bar, and Locked flyout position by @NanthiniMahalingam in
#32701
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS, Mac Catalyst] Shell Flyout and Content Do Not Fully Support
RightToLeft (RTL)](#32419)
  </details>

- [IOS] Inconsistent Resize Behavior for Header/Footer - fix by @kubaflo
in #28713
  <details>
  <summary>🔧 Fixes</summary>

- [[IOS, Mac] Inconsistent Resize Behavior for
Header/Footer](#26397)
- [Enable Shell Flyout Header/Footer resize tests on
iOS/Catalyst](#33501)
  </details>

- [Android] Fix for SearchHandler retaining previous page SearchView
data in pages within Shell sections by @BagavathiPerumal in
#29545
  <details>
  <summary>🔧 Fixes</summary>

- [[Shell][Android] The truth is out there...but not on top tab search
handlers](#8716)
  </details>

- [Android] Fix empty space above TabBar after navigating back when
TabBar visibility is toggled by @praveenkumarkarunanithi in
#34324
  <details>
  <summary>🔧 Fixes</summary>

- [Empty space appears above TabBar after navigating back when TabBar
visibility is toggled](#33703)
- [Grid with SafeAreaEdges=Container has incorrect size when tab bar
appears](#34256)
  </details>

## SwipeView
- [Android] SwipeView: Use MeasureSpecMode.Exactly for SwipeItem layout
to fix text visibility by @Ahamed-Ali in
#27399
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Right SwipeView items are not visible in the
SwipeView.](#27367)
  </details>

- [Android] Prevent the tap that closes an open SwipeView from being
propagated to children by @sjordanGSS in
#24275
  <details>
  <summary>🔧 Fixes</summary>

- [Tapping to close a SwipeView will activate TapGestureRecognizers on
.Content](#23921)
  </details>

## Switch
- [iOS & Mac] Fix for SearchHandler retains previous page state when
switching top tabs by @BagavathiPerumal in
#34735
  <details>
  <summary>🔧 Fixes</summary>

- [[Shell] [iOS & Mac] SearchHandler retains previous page state when
switching top tabs](#34693)
  </details>

## TabbedPage
- [Android] Fixed NullReferenceException in app with TabBar after
returning from minimized state by @NirmalKumarYuvaraj in
#34779
  <details>
  <summary>🔧 Fixes</summary>

- [NullReferenceException in app with TabBar after returning from
minimized state](#34720)
  </details>

## Titlebar
- Fixed BindingContext of the Window TitleBar is not being passed on to
its child content. by @NirmalKumarYuvaraj in
#30080
  <details>
  <summary>🔧 Fixes</summary>

- [The BindingContext of the Window TitleBar is not being passed on to
its child content.](#24831)
  </details>

- [Windows/Mac] Fix RTL FlowDirection causes overlap with native window
control buttons in TitleBar by @devanathan-vaithiyanathan in
#30400
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows, Mac] RTL FlowDirection causes overlap with native window
control buttons in
TitleBar](#30399)
  </details>

## WebView
- [Windows] Fix WebView background color not being applied by
@SubhikshaSf4851 in #34599
  <details>
  <summary>🔧 Fixes</summary>

- [WebView background color has changed after update, can't
override.](#34518)
  </details>

- [Android] Fix for WebView/HybridWebView briefly flashes full screen
before layout completes by @praveenkumarkarunanithi in
#33207
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] HybridWebView briefly resizes to full screen when page is
opened before snapping back to correct
size](#31475)
  </details>

## Xaml
- Improved style inheritance by @kubaflo in
#31317
  <details>
  <summary>🔧 Fixes</summary>

- [Styles based on a style that is based on another style that uses
AppThemeBinding do not inherit properties
correctly.](#31280)
  </details>

- Fix for VisualStateManager Setter.TargetName failing when
ControlTemplate is applied by @BagavathiPerumal in
#33208
  <details>
  <summary>🔧 Fixes</summary>

- [Setter.TargetName + ControlTemplate
crash](#26977)
  </details>


<details>
<summary>🧪 Testing (4)</summary>

- [Testing] Additional Feature Matrix Event Test Cases for Slider and
ScrollView by @nivetha-nagalingam in
#34352
- [Testing] Fixed Build error on inflight/ candidate PR 34885 by
@NafeelaNazhir in #34891
- [Testing] Fixed UI test image failure in PR 34885 - [13/4/2026] by
@NafeelaNazhir in #34933
- Fixed test failure - CursorPositionUpdatesWhenSearchBarGainsFocus by
@Dhivya-SF4094 in #34938

</details>

<details>
<summary>📦 Other (3)</summary>

- Fix Loaded event not called for MAUI View added to native View by
@NirmalKumarYuvaraj in #34345
  <details>
  <summary>🔧 Fixes</summary>

- [Loaded event not called for MAUI View added to native
View](#34310)
  </details>
- Add public IAlertManager and IAlertManagerSubscription interfaces by
@Redth in #34228
  <details>
  <summary>🔧 Fixes</summary>

- [Alert/Dialog system (`DisplayAlert`, `DisplayActionSheet`,
`DisplayPromptAsync`) needs a public extensibility
point](#34104)
  </details>
- Fix crash when displaying alerts on unloaded pages by @kubaflo in
#33288

</details>

<details>
<summary>📝 Issue References</summary>

Fixes #5825, Fixes #8494, Fixes #8716, Fixes #10987, Fixes #11404, Fixes
#12008, Fixes #18200, Fixes #18551, Fixes #18657, Fixes #18701, Fixes
#19168, Fixes #19209, Fixes #20062, Fixes #20348, Fixes #20834, Fixes
#20991, Fixes #21983, Fixes #22038, Fixes #22193, Fixes #22197, Fixes
#22769, Fixes #23330, Fixes #23854, Fixes #23902, Fixes #23921, Fixes
#24304, Fixes #24831, Fixes #25124, Fixes #26059, Fixes #26397, Fixes
#26644, Fixes #26846, Fixes #26961, Fixes #26977, Fixes #27086, Fixes
#27367, Fixes #27959, Fixes #28337, Fixes #28351, Fixes #28660, Fixes
#28975, Fixes #29390, Fixes #29391, Fixes #29463, Fixes #29493, Fixes
#29544, Fixes #30052, Fixes #30065, Fixes #30071, Fixes #30144, Fixes
#30399, Fixes #30779, Fixes #30803, Fixes #30970, Fixes #31280, Fixes
#31446, Fixes #31475, Fixes #31496, Fixes #31565, Fixes #31825, Fixes
#31961, Fixes #32048, Fixes #32050, Fixes #32139, Fixes #32356, Fixes
#32419, Fixes #32771, Fixes #32944, Fixes #32984, Fixes #32994, Fixes
#33308, Fixes #33501, Fixes #33703, Fixes #33770, Fixes #33773, Fixes
#34104, Fixes #34256, Fixes #34257, Fixes #34310, Fixes #34322, Fixes
#34363, Fixes #34370, Fixes #34459, Fixes #34518, Fixes #34583, Fixes
#34591, Fixes #34666, Fixes #34693, Fixes #34720, Fixes #34730

</details>

**Full Changelog**:
main...inflight/candidate
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 30, 2026
@kubaflo kubaflo 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-pr-picked AI could not beat the PR fix - PR is the best among all candidates labels May 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-controls-picker Picker community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-win AI found a better alternative fix than the PR s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[regression/8.0.3] iOS Picker dismiss does not work when clicking outside of the Picker

10 participants