Images in ListView flicker on load

9 posts, 0 answers
  1. Mikhail
    Mikhail avatar
    12 posts
    Member since:
    Jul 2017

    Posted 18 Sep Link to this post

    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

  2. Mikhail
    Mikhail avatar
    12 posts
    Member since:
    Jul 2017

    Posted 18 Sep in reply to Mikhail Link to this post

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

  3. Mikhail
    Mikhail avatar
    12 posts
    Member since:
    Jul 2017

    Posted 19 Sep Link to this post

    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.

  4. Pavel R. Pavlov
    Admin
    Pavel R. Pavlov avatar
    1236 posts

    Posted 21 Sep Link to this post

    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
  5. Mikhail
    Mikhail avatar
    12 posts
    Member since:
    Jul 2017

    Posted 21 Sep Link to this post

    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

  6. Mikhail
    Mikhail avatar
    12 posts
    Member since:
    Jul 2017

    Posted 21 Sep in reply to Mikhail Link to this post

    Working link to solution zip: solution zip
  7. Mikhail
    Mikhail avatar
    12 posts
    Member since:
    Jul 2017

    Posted 22 Sep Link to this post

    Please let me know how to resolve this problem or how soon this is going to be resolved. Thank you.
  8. Justin
    Justin avatar
    1 posts
    Member since:
    Apr 2015

    Posted 27 Sep Link to this post

    I am experiencing these exact same symptoms.  I upgraded to the most recent release after seeing this thread, but the issue persists.  Any updates?
  9. Lance | Tech Support Engineer, Sr.
    Admin
    Lance | Tech Support Engineer, Sr. avatar
    415 posts

    Posted 28 Sep Link to this post

    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
Back to Top