Friday, April 3, 2015

Images in a ListView on iOS

There is an odd behavior in Xamarin Forms regarding images that are loaded from an URL and then placed in an ListView. The problem is that there is an await call when fetching images and that the image is set when that call is returned.

Since Xamarin Forms Listview now reuses cells in iOS (as it should) one small piece was overlooked. The reused cells now displays previously displayed images for a short while until the new image is downloaded.

This behavior is mitigated by a cache, so once an image is loaded it's set instantly the next time the cell is displayed.

I've also filed a bug with a sample project available at https://bugzilla.xamarin.com/show_bug.cgi?id=28628 and the sample project to visualize the issue at here.

There are a number of ways around this.

Suggestion one - half-way around

This solution works, but images are blank and then suddenly pops into place. It's visually ugly, but better than the original version  of the ImageRenderer. What is does is that it sets the Image to null (the UIImage.Image) when IsLoading changes from False to True. The problem is that is does this even when the image isn't loading from the internet, but from the cache as well, leaving us with no option to initiate a fade in.

assembly: ExportRenderer (typeof (Image), typeof (CustomImageRenderer))]

namespace ImageListView.iOS.Renderers
{
    public class CustomImageRenderer : ImageRenderer
    {
        public CustomImageRenderer()
        {
        }

        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if ((sender as Image).IsLoading)
            {
                // The image will be reset in base if there is one already in the cache.
                // If it isn't already loaded we don't want to display the previous image
                // This is however called each time a cell comes into view so it can't
                // be used for opacity fading or likewise...
                // This should be handled by the code in the ImageRenderer
                Control.Image = null;
            }
           
            base.OnElementPropertyChanged(sender, e);
        }
    }
}

Suggestion two - wrap it

Wrap your image in a custom control and handle all the loading and caching yourself.

Suggestion three - rewrite it

Write your own Image-renderer from scratch to take into account when an image is fetched from the cache or not to enable a nice fade in. This is what I hope will come out of the bug report.

Suggestion four - hijack the cache

The next article is going to be about this. But simply put, we highjack the cache and control the image flow from that way. Stay tuned! :D

Summary

I would go with suggestion one for now and wait for the outcome of the bug report.

Have a great one!

3 comments:

  1. Thank you, kind man! I was trying to solve this for two days before I saw your article.

    ReplyDelete
  2. Fast and Furious 8 is actually the eighth installment of the blockbuster franchise of The Fast and the Furious released in 2001 on a worldwide basis thus garnering plethora of appreciation as two debutante hits the right note on action genre. Check out the
    Fast and Furious 8 Release Date

    ReplyDelete