This is a migrated thread and some comments may be shown as answers.

Images in ListView flicker on load

8 Answers 620 Views
ListView
This is a migrated thread and some comments may be shown as answers.
Mikhail
Top achievements
Rank 1
Mikhail asked on 18 Sep 2017, 08:14 PM

I have the following ListView set up.

<telerikDataControls:RadListView x:Name="PeopleListView" BackgroundColor="White"
                                 ItemsSource="{Binding Employees}"
                                 IsItemSwipeEnabled="True"
                                 ItemSwiping="PeopleListView_OnItemSwiping"
                                 SwipeOffset="160, 0, 0, 0"
                                 SwipeThreshold="10"
                                 SelectionGesture="Tap"
                                 SelectionMode="Single"
                                 SelectionChanged="PeopleListView_OnSelectionChanged">
    <telerikDataControls:RadListView.ItemTemplate>
        <DataTemplate>
            <telerikListView:ListViewTemplateCell>
                <telerikListView:ListViewTemplateCell.View>
                    <Grid BackgroundColor="White">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>
 
                        <Image Source="{Binding PhotoData}"
                               Style="{StaticResource EmployeeProfileIconStyle}"
                               Grid.RowSpan="2"
                               Grid.Column="0"></Image>
                        <Label Grid.Column="1" Grid.Row="0" Margin="0,3,0,0"
                               FontSize="Medium" Text="{Binding FullName}"></Label>
                        <Label Grid.Column="1" Grid.Row="1"
                               VerticalTextAlignment="Start" VerticalOptions="Start"
                               Text="{Binding EmployeeTitle}"></Label>
                        <Image Grid.Row="0" Grid.RowSpan="2" Grid.Column="2"
                               VerticalOptions="Center"
                               Source="ic_people_outline"
                               WidthRequest="50"
                               HeightRequest="50"
                               Opacity="0.35"
                               IsVisible="{Binding SubordinateCount, Converter={StaticResource IntToBoolConverter}}">
                        </Image>
                    </Grid>
                </telerikListView:ListViewTemplateCell.View>
            </telerikListView:ListViewTemplateCell>
        </DataTemplate>
    </telerikDataControls:RadListView.ItemTemplate>
 
    <telerikDataControls:RadListView.ItemSwipeContentTemplate>
        <DataTemplate>
            <Grid Margin="0"
                  Padding="0"
                  ColumnSpacing="0"
                  RowSpacing="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="80" />
                    <ColumnDefinition Width="80" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
 
                <StackLayout Grid.Column="0" BackgroundColor="#2474d2" WidthRequest="80">
                    <StackLayout.GestureRecognizers>
                        <TapGestureRecognizer x:Name="EmailTapGestureRecognizer"
                                              Tapped="EmailTapGestureRecognizer_OnTapped"
                                              NumberOfTapsRequired="1"></TapGestureRecognizer>
                    </StackLayout.GestureRecognizers>
                    <Image Source="ic_mail_outline" VerticalOptions="CenterAndExpand"></Image>
                </StackLayout>
 
                <StackLayout Grid.Column="1" BackgroundColor="LimeGreen" WidthRequest="80">
                    <StackLayout.GestureRecognizers>
                        <TapGestureRecognizer x:Name="CallTapGestureRecognizer"
                                              Tapped="CallTapGestureRecognizer_OnTapped"
                                              NumberOfTapsRequired="1"></TapGestureRecognizer>
                    </StackLayout.GestureRecognizers>
                    <Image Source="ic_call" VerticalOptions="CenterAndExpand"></Image>
                </StackLayout>
            </Grid>
        </DataTemplate>
    </telerikDataControls:RadListView.ItemSwipeContentTemplate>
</telerikDataControls:RadListView>

 

The model that is bound to ListView is as follows.

public class Employee
{
    public int EmployeeId { get; set; }
    public int SubordinateCount { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }
    public string EmployeeTitle { get; set; }
    public string FullName => $"{FirstName} {LastName}";
    public ImageSource PhotoData { get; set; }
    // ...
}

 

The PhotoData property is ImageSource type and is obtained from base64 of the image as follows (this all happens before being bound to View).

var imageData = Convert.FromBase64String(GetEmployeePhotoData());
employee.PhotoData = ImageSource.FromStream(() => new MemoryStream(imageData));

 

And Employees (ListView's ItemsSource) is an ObservableCollection<Employee> property in ViewModel.

When I display a list of employees in a ListView everything works fine on Android. However, on iOS the employee photos flicker for 1 - 2 seconds when ListView is displayed. To be precise, it's not flickering, but rather photos change quickly before stabilizing. For example, if I have employees A, B and C in ListView, then on load I see that employee A has employee C's photo for split second, then it quickly changes to employee B's photo. Then it changes again, so that employee A has correct employee A's photo displayed. The similar thing happens for all employees in the list. (The order in which photos "flicker" may or may not be sequential - the order in which people are displayed in the list - because they change so quickly it's hard to tell. But eventually, when "flickering" stops, all employees have correct photos displayed.)

Please let me know what can be done to solve this.

Thanks

8 Answers, 1 is accepted

Sort by
0
Mikhail
Top achievements
Rank 1
answered on 18 Sep 2017, 08:20 PM

As a followup, the flickering does not happen if I use Xamarin.Form's ListView.

0
Mikhail
Top achievements
Rank 1
answered on 19 Sep 2017, 04:26 PM

Ok, I also have a different static image on each item in ListView and it also flickers on load. So, it seems it has nothing to do with image itself or where it came from (static from phone or loaded from the web), but it has to do with binding of data to ListView itself.

It seems ListView's logic for binding data is somewhat faulty, as if ListView gets confused which piece of data belongs to what row in ListView.

0
Pavel R. Pavlov
Telerik team
answered on 21 Sep 2017, 08:42 AM
Hi Mikhail,

We had similar issue in one of our previous releases. However, we managed to apply a fix for it and with our latest official release we cannot reproduce the reported behavior on our side. 

Could you please try the attached project on your side and let us know if the behavior can be observed? If not, we will need additional information regarding your scenario. On which emulator or device you observe it? How many items you load into the control? Is there anything special implemented in the event handlers?

Every additional piece of information you can provide is welcome.

Regards,
Pavel R. Pavlov
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Mikhail
Top achievements
Rank 1
answered on 21 Sep 2017, 09:27 PM

Thanks Pavel. I updated the solution to replicate the problem. I also added icon button to the right of each item in ListView, click on it to observe the behaviour. (Behaviour also shows up on load.)

We tested on iPhone 6, and iPhone Simulator iOS 10 and 11.

List View iOS zip

0
Mikhail
Top achievements
Rank 1
answered on 21 Sep 2017, 09:30 PM
Working link to solution zip: solution zip
0
Mikhail
Top achievements
Rank 1
answered on 22 Sep 2017, 06:08 PM
Please let me know how to resolve this problem or how soon this is going to be resolved. Thank you.
0
Justin
Top achievements
Rank 1
answered on 28 Sep 2017, 01:16 AM
I am experiencing these exact same symptoms.  I upgraded to the most recent release after seeing this thread, but the issue persists.  Any updates?
0
Lance | Manager Technical Support
Telerik team
answered on 28 Sep 2017, 03:11 PM
Hello Justin,

We are currently investigating the underlying cause, but for now I've created a workaround. Open my attached demo and examine StartPage.xaml and EmployeeCell.cs.

Give this approach a try. If it doesn't work please open a support ticket here and attach your code so that I can work on a more specific workaround for your use-case.

Workaround

In summary, the workaround in my demo uses a custom cell so that you have access to the Image element via a reference. With the reference, you can manually clear the Image's source before assigning the new value.

Here is the relevant code:

Custom Cell

The custom cell extends ListViewTemplateCell and nulls out the Source property of the Image:

namespace TelerikXamarinApp2.Portable.CustomCells
{
    public class EmployeeCell : ListViewTemplateCell
    {
        private Image employeeImage;
         
        protected override void OnBindingContextChanged()
        {
            // Get the Image control in the View
            if(employeeImage == null)
                employeeImage = this.View.FindByName<Image>("EmployeePhotoImage");
 
            // Manually clearing the Image's source before updating the value
            employeeImage.Source = null;
 
            base.OnBindingContextChanged();
 
            // Update the Source
            if (BindingContext != null)
                employeeImage.Source = (BindingContext as Employee)?.PhotoData;
        }
    }
}


RadListView ItemTemplate


You'll see that we use the custom cell instead of the base ListViewTemplateCell. notice that the Image has an x:Name of "EmployeeImage". This is necessary in order to get a reference to it, you can name it accordingly.

<telerikDataControls:RadListView ...>
    <telerikDataControls:RadListView.ItemTemplate>
         <DataTemplate>
             <customCells:EmployeeCell>
                 <customCells:EmployeeCell.View>
                    <Grid>
                        ...
                        <Image x:Name="EmployeePhotoImage"  ... "/>
                        ...
                     </Grid>
                </customCells:EmployeeCell.View>
            </customCells:EmployeeCell>
        </DataTemplate>
    </telerikDataControls:RadListView.ItemTemplate>
</telerikDataControls:RadListView>


Wrapping Up

If you have any further questions, you can add them to the ticket that you'll create and I'll address them along with the original problem.

Thank you for contacting Support and for choosing UI for Xamarin.


Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
ListView
Asked by
Mikhail
Top achievements
Rank 1
Answers by
Mikhail
Top achievements
Rank 1
Pavel R. Pavlov
Telerik team
Justin
Top achievements
Rank 1
Lance | Manager Technical Support
Telerik team
Share this question
or