Displaying SVGs in Xamarin.Forms
There is no built-in support for rendering SVG images in Xamarin.Forms, but there are a few NuGet packages you can use to add this functionality. Xamarin.Forms.Svg has worked well for me. It can create an ImageSource
from an SVG so that it can be rendered by Image
view just like other image formats.
I wanted to display a list of items with an image URL and a corresponding test in a ListView
:
<ListView ItemsSource="{Binding Currencies}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Image Source="{Binding LogoUrl}"/>
<Label Text="{Binding Symbol}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This worked fine for bitmap images in PNG and JPG formats, but not for images in SVG format.
To fix this, I installed the Xamarin.Forms.Svg NuGet package in both the native projects and the shared .NET Standard project. I had to initialize the library in the native project as described in the official documentation:
In
MainActivity.OnCreate
for Android:Xamarin.Forms.Svg.Droid.SvgImage.Init(this); LoadApplication(new App());
In
AppDelegate.FinishedLaunching
for iOS:Xamarin.Forms.Svg.iOS.SvgImage.Init(); LoadApplication(new App());
There are several ways to create an ImageSource
from an SVG file. I decided to create a value converter that returns an SvgImageSource
for SVG files and a normal ImageSource
for other file formats:
public class UrlToImageSourceConverter : IValueConverter
{
public object Convert(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
if (value is string)
{
var uriString = (string)value;
Uri uri = new Uri(uriString);
if (uri.AbsolutePath.ToLowerInvariant().EndsWith(".svg"))
{
return SvgImageSource.FromSvgUri(uriString, 200, 200, default(Color));
}
else
{
return ImageSource.FromUri(uri);
}
}
else
{
return null;
}
}
public object ConvertBack(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
}
This allowed me to support the SVG file format with minimal impact on the rest of the code. I did not have to make any changes to the view model. Only in the view did I have to create a resource for the converter and use that in the Image
binding:
<ContentPage.Resources>
<converters:UrlToImageSourceConverter x:Key="ImageSrcConverter" />
</ContentPage.Resources>
<Image Source="{Binding LogoUrl, Converter={StaticResource ImageSrcConverter}}"/>
You can see the full code for the finished project in my GitHub repository.
Although Xamarin.Forms does not support SVG files out of the box, they can be easily rendered using the Xamarin.Forms.Svg NuGet package. I created a value converter that generates the correct image source for each image type: SvgImageSource
from this NuGet package for SVG URLs and the default ImageSource
for all other URLs. This way, no further code changes were required to add SVG support to the application.