diff --git a/src/Controls/src/Core/Handlers/Items/Android/Adapters/SelectableItemsViewAdapter.cs b/src/Controls/src/Core/Handlers/Items/Android/Adapters/SelectableItemsViewAdapter.cs index 41f5619c3ea7..2dfb6e8c0b34 100644 --- a/src/Controls/src/Core/Handlers/Items/Android/Adapters/SelectableItemsViewAdapter.cs +++ b/src/Controls/src/Core/Handlers/Items/Android/Adapters/SelectableItemsViewAdapter.cs @@ -163,9 +163,16 @@ bool PositionIsSelected(int position) void SelectableClicked(object sender, int adapterPosition) { if (adapterPosition >= 0 && adapterPosition < ItemsSource?.Count) - { - UpdateMauiSelection(adapterPosition); - } + { + UpdateMauiSelection(adapterPosition); + // Unconditionally sync visual state for Single mode. + // Handles value-equal items where PropertyChanged is suppressed. + if (ItemsView.SelectionMode == SelectionMode.Single && sender is SelectableViewHolder clickedHolder) + { + ClearPlatformSelection(); + clickedHolder.IsSelected = true; + } + } } void UpdateMauiSelection(int adapterPosition) diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/CollectionViewSelectionChangesVisualState.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/CollectionViewSelectionChangesVisualState.png new file mode 100644 index 000000000000..e0de2abf8af3 Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/CollectionViewSelectionChangesVisualState.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue20062.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue20062.cs new file mode 100644 index 000000000000..efde8d43a3a2 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue20062.cs @@ -0,0 +1,101 @@ +using Microsoft.Maui.Controls.Shapes; + +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 20062, "CollectionView - SelectedItem visual state manager not working", + PlatformAffected.Android)] +public class Issue20062 : TestContentPage +{ + CollectionView _collectionView; + List list = new List(); + + protected override void Init() + { + + _collectionView = new CollectionView + { + SelectionMode = SelectionMode.Single, + ItemsLayout = new GridItemsLayout(2, ItemsLayoutOrientation.Vertical) + { + HorizontalItemSpacing = 12, + VerticalItemSpacing = 12 + }, + ItemTemplate = new DataTemplate(() => + { + var border = new Border + { + Padding = 4, + BackgroundColor = Colors.White, + Stroke = Colors.Gray, + StrokeShape = new RoundRectangle { CornerRadius = 12 }, + StrokeThickness = 1 + }; + + var label = new Label + { + FontFamily = "SemiBold", + TextColor = Colors.Black, + Text = "a", + FontSize = 14, + HorizontalOptions = LayoutOptions.Center, + HorizontalTextAlignment = TextAlignment.Center, + VerticalOptions = LayoutOptions.Center + }; + var grid = new Grid + { + RowDefinitions = + { + new RowDefinition { Height = new GridLength(80) }, + new RowDefinition { Height = new GridLength(40) } + } + }; + + grid.Add(label, 0, 1); + + border.Content = grid; + VisualStateManager.SetVisualStateGroups(border, new VisualStateGroupList + { + new VisualStateGroup + { + Name = "CommonStates", + States = + { + new VisualState { Name = "Normal" }, + new VisualState + { + Name = "Selected", + Setters = + { + new Setter { Property = Border.BackgroundColorProperty, Value = Colors.Blue }, + new Setter { Property = Border.StrokeProperty, Value = Colors.Red } + } + } + } + } + }); + + return border; + }) + }; + _collectionView.AutomationId = "CollectionView"; + + var layout = new VerticalStackLayout + { + Padding = new Thickness(30, 0), + Spacing = 25, + Children = { _collectionView } + }; + list.Add("a"); + list.Add("a"); + list.Add("a"); + list.Add("a"); + _collectionView.ItemsSource = list; + + Content = new ScrollView + { + Content = layout + }; + + } +} + diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/CollectionViewSelectionChangesVisualState.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/CollectionViewSelectionChangesVisualState.png new file mode 100644 index 000000000000..43d131d7b9d9 Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/CollectionViewSelectionChangesVisualState.png differ diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue20062.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue20062.cs new file mode 100644 index 000000000000..b257198b1215 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue20062.cs @@ -0,0 +1,25 @@ +#if TEST_FAILS_ON_WINDOWS // When selecting a single item, the selection background is applied to all items. +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue20062 : _IssuesUITest +{ + public Issue20062(TestDevice device) : base(device) { } + + public override string Issue => "CollectionView - SelectedItem visual state manager not working"; + + [Test] + [Category(UITestCategories.CollectionView)] + public void CollectionViewSelectionChangesVisualState() + { + App.WaitForElement("CollectionView"); + var items = App.FindElementsByText("a"); + items.ElementAt(0).Tap(); + items.ElementAt(2).Tap(); + VerifyScreenshot(); + } +} +#endif \ No newline at end of file diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/CollectionViewSelectionChangesVisualState.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/CollectionViewSelectionChangesVisualState.png new file mode 100644 index 000000000000..c293950eb0fd Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/CollectionViewSelectionChangesVisualState.png differ