Images with placeholder in Xamarin forms


Isn't it fun,

to instantly listen to a blog on the go? PLAY !

 
 

ImageswithplaceholderinXamarin

In this blog, we will see many times the image fails to load at that time we can display a placeholder. In essential the placeholder mechanism is ready. When we load the image from the web they have many chances to fail the image loading that time we can display a placeholder.

What are glindex forms?

The glindex form is a library of the Xamarin forms that implementation of Glide. It is quasi-standard for imaging on Android, and it’s recommended by Google.

Why do we need to extend the library?

The placeholder has been stored in the resources of your android project so if we want to load the placeholder we need to extend the library. And we want to load images from the resources of Xamarin forms or from a font, we will need to extend the GlideExtensions class.

The following step shows how to load a placeholder for images.


Step: 1

Open Visual Studio and select Xamarin project.

Image: Create a Xamarin project

Then give it to the name and select Blank App from Android and iOS platforms.

Image: Select template and platform.



Step: 2

Now, create a one-class file in the Android platform right-click the android project -> Add -> Select Class -> add name and click to add then replace the code with the below code.

using Android.Glide;
using Android.Widget;
using Bumptech.Glide;
using System.Threading;
using Xamarin.Forms;

namespace XfNativeCachedImages.Droid
{
    public class GlideWithAndroidResourcePlaceholder : IGlideHandler
    {
        public GlideWithAndroidResourcePlaceholder()
        {
        }

        public bool BuildImagePlace(ImageView ViewofImage, ImageSource sourceofImage, RequestBuilder requestbuild, CancellationToken Canceltoken)
        {
            if (requestbuild != null)
            {
                //error placeholder:
                requestbuild.Error(Resource.Drawable.MSicc_Logo_Base_Blue_1024px_pad25).Into(ViewofImage);

                return true;
            }
            else
                return false;
        }
    }

}


Step: 3

Now, create one class file in the shared project for creating properties and fields.

ImageViewModel.cs
using System;
using System.Reflection;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;

namespace XfNativeCachedImages
{
    public class ImageViewModel : ObservableObject
    {
        private string _imageUrl;
        private ImageSource _imageFromUrl;

        public ImageViewModel(string imageUrl, string resourceName, Assembly sourceAssembly = null)
        {
            this.ImageUrl = imageUrl;
            this.ImageFromUrl = ImageSource.FromUri(new Uri(this.ImageUrl));
        }


        public string ImageUrl { get => _imageUrl; set => SetProperty(ref _imageUrl, value); }



        public ImageSource ImageFromUrl
        {
            get => _imageFromUrl;
            set
            {
                _imageFromUrl = value;
                OnPropertyChanged(nameof(this.ImageFromUrl));
            }
        }
    }
}


Step: 4

Here, we can create a file for an extension of resources.

ImageResourceExtension.cs
using System;
using System.Reflection;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace XfNativeCachedImages
{
    [ContentProperty(nameof(SourceofImage))]
    public class ImageResourceExtension : IMarkupExtension
    {
        public string SourceofImage { get; set; }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            if (SourceofImage == null)
            {
                return null;
            }

            var imageSource = ImageSource.FromResource(SourceofImage, typeof(ImageResourceExtension).GetTypeInfo().Assembly);

            return imageSource;
        }
    }
}


Step: 5

After that, we can come up with our Xaml part. Create a design as we want or add the below code to your Xaml page.

MainPage.Xaml




    
        
            
                

    

    
        
            
                

    


Here, we can replace the content page with a Tabbed page. Using a tabbed page, we can display images on different pages or tabs. Inside the tabbed page, we can add a content page to display the content.

On this tabbed page, we can add two content pages, On the first content page, we can bind the title, images, and local images. In the second content page we can display data in the collection view, inside the collection view we can bind the label and images.


Searching for the Best Xamarin App Development Company ?

Your Search ends here.



Step: 6

MainPage.Xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace XfNativeCachedImages
{
    public partial class MainPage : TabbedPage
    {
        public MainPage()
        {
            InitializeComponent();

            this.SingleImagesTabPage.IconImageSource = new FontImageSource()
            {
                Glyph = XfNativeCachedImages.Resources.MaterialDesignIcons.FileImage,
                FontFamily = "MaterialDesignIcons",
            };

            this.CollectionViewTabpage.IconImageSource = new FontImageSource()
            {
                Glyph = XfNativeCachedImages.Resources.MaterialDesignIcons.FormatListBulleted,
                FontFamily = "MaterialDesignIcons",
            };

            var mainVm = new MainViewModel();
            mainVm.Init();

            this.BindingContext = mainVm;   
        }
    }
}

We can bind the view model with this .cs file.


Step: 7

MainViewModel.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;

namespace XfNativeCachedImages
{
    public class MainViewModel : ObservableObject
    {
        private const string _placeholderResource = "CachedImageTest.png";

        private Uri _image1Uri;
        private Uri _image2Uri;
        private ImageSource _image1WithPlaceholderImageSource;

        public MainViewModel()
        {
        }

        public void Init()
        {
            this.Image1Uri = new Uri("https://msicc.net/wp-content/uploads/2020/12/img_7087-scale.jpg");

            this.Image2Uri = new Uri("https://msicc.net/wp-content/uploads/2020/07/ScrollableTabsXF_Title.png");

            this.Image1WithPlaceholderSource = new UriImageSource();

            var imgUrlsFromJson = LoadUrlsFromJson();
            var imgsList = imgUrlsFromJson.Where(u => !string.IsNullOrEmpty(u)).Select(u => new ImageViewModel(u, _placeholderResource)).ToList();

            this.ImagesFromUrl = new ObservableCollection(imgsList);


        }

        private List LoadUrlsFromJson()
        {
            string jsonFileName = "ImageUrls.json";
            var assembly = this.GetType().Assembly;
            Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{jsonFileName}");
            using var reader = new StreamReader(stream);
            var jsonString = reader.ReadToEnd();

            return JsonConvert.DeserializeObject>(jsonString);
        }

        public string Title => "Cached Image Test with Placeholder";

        public Uri Image1Uri { get => _image1Uri; set => SetProperty(ref _image1Uri, value); }

        public Uri Image2Uri { get => _image2Uri; set => SetProperty(ref _image2Uri, value); }

        public ImageSource Image1WithPlaceholderSource { get => _image1WithPlaceholderImageSource; set => SetProperty(ref _image1WithPlaceholderImageSource, value); }

        public ObservableCollection ImagesFromUrl { get; set; }

    }
}

We can bind the view model with the main view, in this view model we can store the image path and we can load URLs from the JSON.

Conclusion

As we can see in this tutorial, the webserver is not loaded image every time a few times we might fail to load the image that’s why we can display a placeholder when the image is not loaded. We can also implement a custom GlideExtensions class of the glindex forms but when we want to load an image from the Xamarin.forms resource we will need to extend the GlideExtensions class.

ImageswithplaceholderinXamarin

In this blog, we will see many times the image fails to load at that time we can display a placeholder. In essential the placeholder mechanism is ready. When we load the image from the web they have many chances to fail the image loading that time we can display a placeholder.

What are glindex forms?

The glindex form is a library of the Xamarin forms that implementation of Glide. It is quasi-standard for imaging on Android, and it’s recommended by Google.

Why do we need to extend the library?

The placeholder has been stored in the resources of your android project so if we want to load the placeholder we need to extend the library. And we want to load images from the resources of Xamarin forms or from a font, we will need to extend the GlideExtensions class.

The following step shows how to load a placeholder for images.


Step: 1

Open Visual Studio and select Xamarin project.

Image: Create a Xamarin project

Then give it to the name and select Blank App from Android and iOS platforms.

Image: Select template and platform.



Step: 2

Now, create a one-class file in the Android platform right-click the android project -> Add -> Select Class -> add name and click to add then replace the code with the below code.

using Android.Glide;
using Android.Widget;
using Bumptech.Glide;
using System.Threading;
using Xamarin.Forms;

namespace XfNativeCachedImages.Droid
{
    public class GlideWithAndroidResourcePlaceholder : IGlideHandler
    {
        public GlideWithAndroidResourcePlaceholder()
        {
        }

        public bool BuildImagePlace(ImageView ViewofImage, ImageSource sourceofImage, RequestBuilder requestbuild, CancellationToken Canceltoken)
        {
            if (requestbuild != null)
            {
                //error placeholder:
                requestbuild.Error(Resource.Drawable.MSicc_Logo_Base_Blue_1024px_pad25).Into(ViewofImage);

                return true;
            }
            else
                return false;
        }
    }

}


Step: 3

Now, create one class file in the shared project for creating properties and fields.

ImageViewModel.cs
using System;
using System.Reflection;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;

namespace XfNativeCachedImages
{
    public class ImageViewModel : ObservableObject
    {
        private string _imageUrl;
        private ImageSource _imageFromUrl;

        public ImageViewModel(string imageUrl, string resourceName, Assembly sourceAssembly = null)
        {
            this.ImageUrl = imageUrl;
            this.ImageFromUrl = ImageSource.FromUri(new Uri(this.ImageUrl));
        }


        public string ImageUrl { get => _imageUrl; set => SetProperty(ref _imageUrl, value); }



        public ImageSource ImageFromUrl
        {
            get => _imageFromUrl;
            set
            {
                _imageFromUrl = value;
                OnPropertyChanged(nameof(this.ImageFromUrl));
            }
        }
    }
}


Step: 4

Here, we can create a file for an extension of resources.

ImageResourceExtension.cs
using System;
using System.Reflection;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace XfNativeCachedImages
{
    [ContentProperty(nameof(SourceofImage))]
    public class ImageResourceExtension : IMarkupExtension
    {
        public string SourceofImage { get; set; }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            if (SourceofImage == null)
            {
                return null;
            }

            var imageSource = ImageSource.FromResource(SourceofImage, typeof(ImageResourceExtension).GetTypeInfo().Assembly);

            return imageSource;
        }
    }
}


Step: 5

After that, we can come up with our Xaml part. Create a design as we want or add the below code to your Xaml page.

MainPage.Xaml




    
        
            
                

    

    
        
            
                

    


Here, we can replace the content page with a Tabbed page. Using a tabbed page, we can display images on different pages or tabs. Inside the tabbed page, we can add a content page to display the content.

On this tabbed page, we can add two content pages, On the first content page, we can bind the title, images, and local images. In the second content page we can display data in the collection view, inside the collection view we can bind the label and images.


Searching for the Best Xamarin App Development Company ?

Your Search ends here.



Step: 6

MainPage.Xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace XfNativeCachedImages
{
    public partial class MainPage : TabbedPage
    {
        public MainPage()
        {
            InitializeComponent();

            this.SingleImagesTabPage.IconImageSource = new FontImageSource()
            {
                Glyph = XfNativeCachedImages.Resources.MaterialDesignIcons.FileImage,
                FontFamily = "MaterialDesignIcons",
            };

            this.CollectionViewTabpage.IconImageSource = new FontImageSource()
            {
                Glyph = XfNativeCachedImages.Resources.MaterialDesignIcons.FormatListBulleted,
                FontFamily = "MaterialDesignIcons",
            };

            var mainVm = new MainViewModel();
            mainVm.Init();

            this.BindingContext = mainVm;   
        }
    }
}

We can bind the view model with this .cs file.


Step: 7

MainViewModel.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;

namespace XfNativeCachedImages
{
    public class MainViewModel : ObservableObject
    {
        private const string _placeholderResource = "CachedImageTest.png";

        private Uri _image1Uri;
        private Uri _image2Uri;
        private ImageSource _image1WithPlaceholderImageSource;

        public MainViewModel()
        {
        }

        public void Init()
        {
            this.Image1Uri = new Uri("https://msicc.net/wp-content/uploads/2020/12/img_7087-scale.jpg");

            this.Image2Uri = new Uri("https://msicc.net/wp-content/uploads/2020/07/ScrollableTabsXF_Title.png");

            this.Image1WithPlaceholderSource = new UriImageSource();

            var imgUrlsFromJson = LoadUrlsFromJson();
            var imgsList = imgUrlsFromJson.Where(u => !string.IsNullOrEmpty(u)).Select(u => new ImageViewModel(u, _placeholderResource)).ToList();

            this.ImagesFromUrl = new ObservableCollection(imgsList);


        }

        private List LoadUrlsFromJson()
        {
            string jsonFileName = "ImageUrls.json";
            var assembly = this.GetType().Assembly;
            Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{jsonFileName}");
            using var reader = new StreamReader(stream);
            var jsonString = reader.ReadToEnd();

            return JsonConvert.DeserializeObject>(jsonString);
        }

        public string Title => "Cached Image Test with Placeholder";

        public Uri Image1Uri { get => _image1Uri; set => SetProperty(ref _image1Uri, value); }

        public Uri Image2Uri { get => _image2Uri; set => SetProperty(ref _image2Uri, value); }

        public ImageSource Image1WithPlaceholderSource { get => _image1WithPlaceholderImageSource; set => SetProperty(ref _image1WithPlaceholderImageSource, value); }

        public ObservableCollection ImagesFromUrl { get; set; }

    }
}

We can bind the view model with the main view, in this view model we can store the image path and we can load URLs from the JSON.

Conclusion

As we can see in this tutorial, the webserver is not loaded image every time a few times we might fail to load the image that’s why we can display a placeholder when the image is not loaded. We can also implement a custom GlideExtensions class of the glindex forms but when we want to load an image from the Xamarin.forms resource we will need to extend the GlideExtensions class.