KEMBAR78
Fix for Preventing Incorrect TalkBack Announcements During CollectionView Deselection on Android by praveenkumarkarunanithi · Pull Request #29818 · dotnet/maui · GitHub
Skip to content

Conversation

praveenkumarkarunanithi
Copy link
Contributor

@praveenkumarkarunanithi praveenkumarkarunanithi commented Jun 4, 2025

Root Cause

The issue arises from how Android's CollectionView manages selection state changes in combination with TalkBack accessibility announcements. The original implementation followed a "clear all and reselect" strategy: it first cleared all selections using adapter.ClearPlatformSelection(), then reselected each item by calling adapter.MarkPlatformSelection(item).

When TalkBack is active, it detects these selection state changes. However, it typically does not announce deselections (i.e., when IsSelected changes from true to false), but it does announce selections (false to true). As a result, when a user deselects an item, TalkBack incorrectly announces one of the reselected items (often the first one), leading to a misleading and confusing accessibility experience.

Description of Change

To resolve the issue, the selection update logic in CollectionView was restructured to avoid the "clear and reselect" pattern. The MarkPlatformSelection method in SelectableItemsViewAdapter.cs was updated to accept the full SelectableItemsView rather than a single item. Within this method, selection states are now processed in a single pass using a HashSet for efficient lookup, updating only the items whose selection states have actually changed. This eliminates unnecessary deselect/reselect cycles and prevents incorrect TalkBack announcements. Additionally, the missing line ItemView.Selected = _isSelected was added to SelectableViewHolder.cs to ensure that the native selection visual state aligns with the logical selection state. Finally, RecyclerViewExtensions.UpdateSelection was simplified to make a single call to MarkPlatformSelection, centralizing the selection logic and improving maintainability.

Issues Fixed

Fixes #29455

Tested the behaviour in the following platforms

  • Android
  • Windows
  • iOS
  • Mac

Note

iOS/macCatalyst test exclusion needs to be removed once accessibility implementation is restored (originally reverted in #29827)

Output Screenshot

Before Issue Fix After Issue Fix
withoutfix.mov
withfix.mov

@dotnet-policy-service dotnet-policy-service bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Jun 4, 2025
@praveenkumarkarunanithi praveenkumarkarunanithi added platform/android area-controls-collectionview CollectionView, CarouselView, IndicatorView t/a11y Relates to accessibility and removed community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Jun 4, 2025
@vishnumenon2684 vishnumenon2684 added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Jun 4, 2025
@jsuarezruiz
Copy link
Contributor

/azp run MAUI-UITests-public

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@praveenkumarkarunanithi praveenkumarkarunanithi marked this pull request as ready for review June 10, 2025 11:06
@praveenkumarkarunanithi praveenkumarkarunanithi requested a review from a team as a code owner June 10, 2025 11:07
@jsuarezruiz
Copy link
Contributor

This PR should also fix #30833

@jsuarezruiz
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

}

var position = GetPositionForItem(selectedItem);
HashSet<object> selectedSet;
Copy link
Contributor

Choose a reason for hiding this comment

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

The MarkPlatformSelection method creates a new HashSet<object> on every call, which could impact performance during frequent selection changes. Could create a single one, and reuse it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jsuarezruiz Thanks for the feedback. I’ve updated the fix to reuse a single _selectedSet by clearing and updating it instead of creating a new HashSet<object> each time.

@PureWeen PureWeen added this to the .NET 9 SR12 milestone Sep 10, 2025
@PureWeen PureWeen moved this from Todo to Ready To Review in MAUI SDK Ongoing Sep 10, 2025
@PureWeen PureWeen added the p/0 Work that we can't release without label Sep 10, 2025
@Copilot Copilot AI review requested due to automatic review settings September 11, 2025 10:45
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes incorrect TalkBack announcements during CollectionView deselection on Android by restructuring the selection update logic to avoid unnecessary clear-and-reselect cycles that confuse accessibility services.

Key changes:

  • Replaced the "clear all and reselect" pattern with a single-pass update that only modifies items whose selection state actually changed
  • Added missing native selection state synchronization to ensure visual state aligns with logical state
  • Centralized selection logic to improve maintainability and prevent TalkBack from announcing incorrect items during deselection

Reviewed Changes

Copilot reviewed 6 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue21375.cs Adds UI test for CollectionView selection behavior with accessibility considerations
src/Controls/tests/TestCases.HostApp/Issues/Issue21375.xaml.cs Creates test page demonstrating CollectionView selection across different platforms
src/Controls/tests/TestCases.HostApp/Issues/Issue21375.xaml Defines XAML layout for the CollectionView selection test page
src/Controls/src/Core/Platform/Android/Extensions/RecyclerViewExtensions.cs Simplifies selection update logic to use centralized method call
src/Controls/src/Core/Handlers/Items/Android/SelectableViewHolder.cs Adds missing native selection state synchronization
src/Controls/src/Core/Handlers/Items/Android/Adapters/SelectableItemsViewAdapter.cs Refactors selection logic to avoid clear-and-reselect pattern that causes TalkBack issues

@@ -0,0 +1,51 @@
#if !IOS && !MACCATALYST // Test excluded for iOS/macCatalyst as the accessibility implementation was reverted in PR-https://github.com/dotnet/maui/pull/29827
Copy link

Copilot AI Sep 11, 2025

Choose a reason for hiding this comment

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

The test case has been properly created in TestCases.Shared.Tests and has a corresponding UI implementation in TestCases.HostApp. The test includes appropriate automation IDs and validates the expected behavior through screenshot verification, which aligns with the testing guidelines.

Copilot uses AI. Check for mistakes.

}

internal void MarkPlatformSelection(object selectedItem)
internal void MarkPlatformSelection(SelectableItemsView selectableItemsView)
Copy link

Copilot AI Sep 11, 2025

Choose a reason for hiding this comment

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

This change modifies the method signature of MarkPlatformSelection from accepting a single item to accepting a SelectableItemsView. This is a potentially breaking change to the internal API that should be reviewed carefully, as it affects how selection state is managed across the platform.

Copilot uses AI. Check for mistakes.

@PureWeen
Copy link
Member

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@PureWeen
Copy link
Member

/rebase

@PureWeen
Copy link
Member

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@PureWeen PureWeen requested review from PureWeen and removed request for StephaneDelcroix and tj-devel709 September 12, 2025 21:40
@github-project-automation github-project-automation bot moved this from Ready To Review to Approved in MAUI SDK Ongoing Sep 16, 2025
@PureWeen PureWeen merged commit 5a07173 into dotnet:main Sep 16, 2025
129 checks passed
@github-project-automation github-project-automation bot moved this from Approved to Done in MAUI SDK Ongoing Sep 16, 2025
@github-actions github-actions bot locked and limited conversation to collaborators Oct 16, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-controls-collectionview CollectionView, CarouselView, IndicatorView p/0 Work that we can't release without partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android t/a11y Relates to accessibility

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Accessibility] CollectionView Selected on Android

4 participants