Description
Description
We experienced some weird behavior when using a CollectionView to display items with a couple icons.
When scrolling through the CollectionView, we noticed some of the icons where displayed in the wrong place. For example, some icons were shown in locations that shouldn't display an icon at all.
We found out that this behavior only occurred on Android, when using a StreamImageSource. We weren't able to reproduce this issue on iOS and Windows, or when using a FileImageSource.
To make sure this wasn't because of our implementation, we managed to reproduce the issue in a simple Maui application, a linkt to this project is added below.
This is how it works:
We have a single page consisting of the CollectionView with a DataTemplate containing a couple labels and images:
<CollectionView ItemsSource="{Binding Items}" BackgroundColor="White">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid RowSpacing="0" Padding="12">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ItemTappedCommand, Source={x:Reference Page}}" CommandParameter="{Binding .}" />
</Grid.GestureRecognizers>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Text="{Binding Name}" LineBreakMode="WordWrap" TextColor="Black"/>
<StackLayout Grid.Row="2" Orientation="Horizontal">
<Label HorizontalOptions="StartAndExpand" Text="{Binding Description}" LineBreakMode="WordWrap" TextColor="Black"/>
<my:Image HorizontalOptions="End" CustomImageSource="{Binding ImageSource1}" WidthRequest="16" HeightRequest="16"/>
<my:Image HorizontalOptions="End" CustomImageSource="{Binding ImageSource2}" WidthRequest="16" HeightRequest="16"/>
<my:Image HorizontalOptions="End" CustomImageSource="{Binding ImageSource3}" WidthRequest="16" HeightRequest="16"/>
</StackLayout>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
The GestureRecognizer is to verify whether the tapped item should display a third icon or not.
The item that we are displaying is a simple object with a name, description and three file names. These file names are all strings and are used in the custom image control to load the image via a stream.
When the value of the CustomImageSource property is changed a task is queued to update the Source property of the image. This queue is added to make sure the sequence of tasks is always correct (we want to rule out that the issue we're having is due to timing). It is, however, still possible (maybe even easier) to reproduce this issue when not utilizing the queue. This is how we retrieve the image and update the Source:
private async Task SetImageAsync(string imageSource, int instanceNumber)
{
await Dispatcher.DispatchAsync(() => Source = null);
if (string.IsNullOrEmpty(imageSource))
{
return;
}
// Loading images from stream has an issue when used in a collection view.
// Make sure the test_icon* files have the right build action (Embedded resource).
// Await makes it easier to reproduce the issue.
await Task.Delay(1000);
var assembly = Assembly.GetExecutingAssembly();
Stream? stream = assembly.GetManifestResourceStream($"IconsTestApp.Resources.Images.{imageSource}");
if (stream == null)
{
return;
}
ImageSource streamImageSource = ImageSource.FromStream(() => stream);
//Loading image from file doesn't have the issue.
// Make sure the test_icon* files have the right build action (Maui image).
//ImageSource fileImageSource = ImageSource.FromFile(imageSource);
await Dispatcher.DispatchAsync(() => Source = streamImageSource);
}
The await is used to make it easier to reproduce the issue. When the source is updated fast enough, this becomes much harder.
Below is a recording of the issue (notice how the first three items shouldn't have a third icon):
Icon.issue.Android.Emulator.mp4
We're fairly certain this issue is a result of using a StreamImageSource in combination with the recycling mechanism of the CollectionView.
I'd also like to point out that this did work when we were still using Xamarin, we did however use the FFImageLoading library so that might have been the reason the issue wasn't present when using Xamarin.
Finally, at the time of writing we are using version 8.0.60, but this issue was also present in previous versions (we haven't tested all of them).
Steps to Reproduce
- Install the linked project.
- Start the project (on an Android device/emulator).
- Scroll down the list of items as fast as possible.
- Scroll up again.
- Most likely some items display a third icon, even though they shouldn't.
Link to public reproduction project repository
https://github.com/Leonardo-pixel/IconsTestApp
Version with bug
8.0.60 SR6
Is this a regression from previous behavior?
Yes, this used to work in Xamarin.Forms
Last version that worked well
Unknown/Other
Affected platforms
Android
Affected platform versions
No response
Did you find any workaround?
A work-around could be to use a FileImageSource instead, however in our actual application, we download the icons we want to display and having to convert these to a FileImageSource would result in a (probably big) performance hit.
Relevant log output
No response