[Android] Fix Picker IsOpen not reset when picker is dismissed#33332
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request fixes an Android-specific issue where the Picker's IsOpen property was not being reset to false when the picker dialog was dismissed via the cancel button or by tapping outside the dialog. The fix adds a single line to set VirtualView.IsOpen = false in the OnDialogDismiss event handler, bringing Android's behavior in line with iOS and Windows platforms which already handle this correctly.
Key Changes:
- Added
VirtualView.IsOpen = falsein Android's PickerHandler when dialog is dismissed - Created UI test to verify the IsOpen property resets correctly after dismissing the picker
- Created HostApp test page to demonstrate and test the fix
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/Core/src/Handlers/Picker/PickerHandler.Android.cs |
Added VirtualView.IsOpen = false in OnDialogDismiss method to reset IsOpen property when picker is dismissed |
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33331.cs |
Added NUnit test to verify IsOpen property behavior with platform-specific dismiss actions (currently excludes Windows) |
src/Controls/tests/TestCases.HostApp/Issues/Issue33331.cs |
Added test page with Picker, button to open programmatically, and label to display IsOpen state |
| @@ -0,0 +1,40 @@ | |||
| # if TEST_FAILS_ON_WINDOWS // This is Android Specific issues | |||
There was a problem hiding this comment.
According to the UI Testing Guidelines, tests should run on all applicable platforms by default unless there is a specific technical limitation. This test is currently restricted to exclude Windows using the preprocessor directive, but based on the PR description indicating the fix was tested on Windows (and Windows also properly sets IsOpen = false in PickerHandler.Windows.cs), there doesn't appear to be a technical reason to exclude Windows.
The comment "This is Android Specific issues" is inaccurate since the IsOpen property behavior should be consistent across all platforms. Remove the TEST_FAILS_ON_WINDOWS directive and allow the test to run on all platforms.
There was a problem hiding this comment.
I think it is a valid comment. If the test is indeed failing on Windows then, can you add a comment why
| #if ANDROID | ||
| App.Tap("Cancel"); | ||
| #elif IOS || MACCATALYST | ||
| // On iOS, tap Done button | ||
| App.Tap("Done"); | ||
| #endif |
There was a problem hiding this comment.
The platform-specific conditional compilation in this test is unnecessarily complex and goes against the UI testing guidelines which state tests should run on all platforms by default.
The test currently has Android-specific Cancel button tapping and iOS/MacCatalyst-specific Done button tapping, but Windows is excluded entirely. However, the behavior being tested (IsOpen property resetting when picker is dismissed) should work consistently across all platforms.
Consider refactoring this test to work across all platforms without platform-specific directives. Since the core assertion is checking that IsOpen returns to False after the picker is dismissed, you could use a more generic approach such as tapping outside the picker or using a platform-agnostic dismiss action that works across all platforms.
| @@ -0,0 +1,40 @@ | |||
| # if TEST_FAILS_ON_WINDOWS // This is Android Specific issues | |||
There was a problem hiding this comment.
There's a spacing inconsistency in this preprocessor directive. Line 1 has a space between '#' and 'if' (written as '# if'), while the closing directive on line 40 uses the standard '#endif' without a space.
Change line 1 to use the standard format without a space: '#if TEST_FAILS_ON_WINDOWS' to match the closing '#endif'.
| # if TEST_FAILS_ON_WINDOWS // This is Android Specific issues | |
| #if TEST_FAILS_ON_WINDOWS // This is Android Specific issues |
|
|
||
| App.Tap("OpenPickerButton"); | ||
|
|
||
| #if ANDROID |
There was a problem hiding this comment.
I agree with the comment here https://github.com/dotnet/maui/pull/33332/changes#r2655473347
Can we move this to an extention method so it's just generalized opening and closing pickers?
|
/rebase |
230a36f to
f4598cd
Compare
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
PR Review: #33332 - [Android] Fix Picker IsOpen not reset when picker is dismissedDate: 2026-01-05 | Issue: #33331 | PR: #33332 ✅ Final Recommendation: APPROVE
📋 Issue SummaryOn Android, when a Picker is dismissed by tapping outside the dialog or pressing the cancel button, the Steps to Reproduce:
Platforms Affected: Android only 📁 Files Changed
🔬 Phase 0: Gate - Test VerificationStatus: ✅ PASSED
Result:
🔍 Phase 1: Independent AnalysisStatus: ✅ PASSED Root Cause: Platform Comparison:
Alternative Approaches Considered:
Conclusion: The PR's approach ( ⚖️ Phase 2: Compare ApproachesStatus: ✅ PASSED
The PR's fix is identical to what I would have done:
🧪 Phase 3: Regression TestingStatus: ✅ PASSED Edge Cases Verified:
All Dismiss Paths Covered:
Potential Regressions: None identified - fix only adds behavior, doesn't change existing behavior. 💬 PR Discussion Summary
Reviewer Feedback (All Addressed):
Justification for Approval:
|
1f825ab to
e291995
Compare
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When the Picker dialog is closed using the cancel button or tapping outside, the IsOpen property is not updated. Even though the Picker is no longer visible, IsOpen stays true, causing the Picker state to be incorrect. ### Description of Change Updated the Android Picker handler to reset VirtualView.IsOpen to false when the picker dialog is dismissed. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33331 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5dc18c5f-a2d2-48cd-95eb-d150b210c4ce" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/c30f015d-5d2b-46cc-9bc1-d07ba9ed485c" width="300" height="600"> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When the Picker dialog is closed using the cancel button or tapping outside, the IsOpen property is not updated. Even though the Picker is no longer visible, IsOpen stays true, causing the Picker state to be incorrect. ### Description of Change Updated the Android Picker handler to reset VirtualView.IsOpen to false when the picker dialog is dismissed. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33331 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5dc18c5f-a2d2-48cd-95eb-d150b210c4ce" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/c30f015d-5d2b-46cc-9bc1-d07ba9ed485c" width="300" height="600"> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When the Picker dialog is closed using the cancel button or tapping outside, the IsOpen property is not updated. Even though the Picker is no longer visible, IsOpen stays true, causing the Picker state to be incorrect. ### Description of Change Updated the Android Picker handler to reset VirtualView.IsOpen to false when the picker dialog is dismissed. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33331 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5dc18c5f-a2d2-48cd-95eb-d150b210c4ce" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/c30f015d-5d2b-46cc-9bc1-d07ba9ed485c" width="300" height="600"> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When the Picker dialog is closed using the cancel button or tapping outside, the IsOpen property is not updated. Even though the Picker is no longer visible, IsOpen stays true, causing the Picker state to be incorrect. ### Description of Change Updated the Android Picker handler to reset VirtualView.IsOpen to false when the picker dialog is dismissed. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33331 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5dc18c5f-a2d2-48cd-95eb-d150b210c4ce" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/c30f015d-5d2b-46cc-9bc1-d07ba9ed485c" width="300" height="600"> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When the Picker dialog is closed using the cancel button or tapping outside, the IsOpen property is not updated. Even though the Picker is no longer visible, IsOpen stays true, causing the Picker state to be incorrect. ### Description of Change Updated the Android Picker handler to reset VirtualView.IsOpen to false when the picker dialog is dismissed. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33331 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5dc18c5f-a2d2-48cd-95eb-d150b210c4ce" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/c30f015d-5d2b-46cc-9bc1-d07ba9ed485c" width="300" height="600"> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When the Picker dialog is closed using the cancel button or tapping outside, the IsOpen property is not updated. Even though the Picker is no longer visible, IsOpen stays true, causing the Picker state to be incorrect. ### Description of Change Updated the Android Picker handler to reset VirtualView.IsOpen to false when the picker dialog is dismissed. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33331 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5dc18c5f-a2d2-48cd-95eb-d150b210c4ce" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/c30f015d-5d2b-46cc-9bc1-d07ba9ed485c" width="300" height="600"> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When the Picker dialog is closed using the cancel button or tapping outside, the IsOpen property is not updated. Even though the Picker is no longer visible, IsOpen stays true, causing the Picker state to be incorrect. ### Description of Change Updated the Android Picker handler to reset VirtualView.IsOpen to false when the picker dialog is dismissed. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33331 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5dc18c5f-a2d2-48cd-95eb-d150b210c4ce" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/c30f015d-5d2b-46cc-9bc1-d07ba9ed485c" width="300" height="600"> |
## What's Coming .NET MAUI inflight/candidate introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 16 commits with various improvements, bug fixes, and enhancements. ## Checkbox - [Android] Implement material3 support for CheckBox by @HarishwaranVijayakumar in #33339 <details> <summary>🔧 Fixes</summary> - [Implement Material3 Support for CheckBox](#33338) </details> ## CollectionView - [Android] Fixed EmptyView doesn’t display when CollectionView is placed inside a VerticalStackLayout by @NanthiniMahalingam in #33134 <details> <summary>🔧 Fixes</summary> - [CollectionView does not show an EmptyView template with an empty collection](#32932) </details> ## Essentials - [Windows]Fix NullReferenceException in OpenReadAsync for FileResult created with full path by @devanathan-vaithiyanathan in #28238 <details> <summary>🔧 Fixes</summary> - [[Windows] FileResult(string fullPath) not initialized properly](#26858) </details> ## Image - Fix Glide IllegalArgumentException in MauiCustomTarget.clear() for destroyed activities by @jfversluis via @Copilot in #29780 <details> <summary>🔧 Fixes</summary> - [java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity - glide](#29699) </details> ## Label - [Android] Fix for Label WordWrap width issue causing HorizontalOptions misalignment by @praveenkumarkarunanithi in #33281 <details> <summary>🔧 Fixes</summary> - [[Android] Unexpected Line Breaks in Android, Label with WordWrap Mode Due to Trailing Space.](#31782) - [Label not sized correctly on Android](#27614) </details> - Fix to Improve Flyout Accessibility by Adjusting UITableViewController Labels by @SuthiYuvaraj in #31619 <details> <summary>🔧 Fixes</summary> - [Navigation section present under hamburger are programmatically define as table :A11y_.NET maui_User can get all the insights of Dashboard_Devtools](#30894) </details> ## Mediapicker - [Regression][iOS] Fix MediaPicker PickPhotosAsync getting file name in contentType property by @devanathan-vaithiyanathan in #33390 <details> <summary>🔧 Fixes</summary> - [[iOS] MediaPicker PickPhotosAsync getting file name in contentType property](#33348) </details> ## Navigation - Fix handler not disconnected when removing non visible pages using RemovePage() by @Vignesh-SF3580 in #32289 <details> <summary>🔧 Fixes</summary> - [NavigationPage.Navigation.RemovePage() fails to disconnect handlers when removing pages, unlike ContentPage.Navigation.RemovePage()](#32239) </details> ## Picker - [Android] Fix Picker IsOpen not reset when picker is dismissed by @devanathan-vaithiyanathan in #33332 <details> <summary>🔧 Fixes</summary> - [[Android] Picker IsOpen not reset when picker is dismissed](#33331) </details> ## Shell - [iOS & Catalyst ] Fixed IsEnabled property should work on Tabs by @SubhikshaSf4851 in #33369 <details> <summary>🔧 Fixes</summary> - [[Catalyst] TabBarBackgroundColor, TabBarUnselectedColor, and IsEnabled Not Working as Expected in Shell](#33158) </details> - [iOS,Windows] Fix navigation bar colors not resetting when switching ShellContent by @Vignesh-SF3580 in #33228 <details> <summary>🔧 Fixes</summary> - [[iOS, Windows] Shell Navigation bar colors are not updated correctly when switching ShellContent](#33227) </details> - [iOS] Fixed Shell navigation on search handler suggestion selection by @SubhikshaSf4851 in #33406 <details> <summary>🔧 Fixes</summary> - [[iOS] Clicking on search suggestions fails to navigate to detail page correctly](#33356) </details> ## Templates - Fix VoiceOver doesnot announces the State of the ComboBox by @SuthiYuvaraj in #32286 ## Xaml - [XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm ObservablePropertyAttribute by @simonrozsival via @Copilot in #33028 <details> <summary>🔧 Fixes</summary> - [[XSG] Add heuristic to support bindable properties generated by other source generators](#32597) </details> <details> <summary>📦 Other (2)</summary> - [XSG] Improve diagnostic reporting during binding compilation by @simonrozsival via @Copilot in #32905 - [Testing] Fixed Test case failure in PR 33574 - [01/19/2026] Candidate - 1 by @TamilarasanSF4853 in #33602 </details> **Full Changelog**: main...inflight/candidate
Issue Details
When the Picker dialog is closed using the cancel button or tapping outside, the IsOpen property is not updated. Even though the Picker is no longer visible, IsOpen stays true, causing the Picker state to be incorrect.
Description of Change
Updated the Android Picker handler to reset VirtualView.IsOpen to false when the picker dialog is dismissed.
Issues Fixed
Fixes #33331
Tested the behavior in the following platforms.
Before.mov
After.mov