Skip to content
Thierry Vilmart edited this page Jun 8, 2020 · 32 revisions

SVG support

SVG files are now working and support every FFImageLoading's feature. It uses SkiaSharp for rendering. If SVG file isn't loading, try to optimise file first using this: https://jakearchibald.github.io/svgomg/ (or cmd only https://github.com/svg/svgo and add it to your pre-build scripts)

Data URLs support

FFImageLoading now supports loading data as data: urls or plain SVG.

  • data:image/svg+xml;base64,[BASE64ENCODEDSVGFILE]
  • <SVG>NOT_ENCODED_SVGFILECONTENT</SVG>
  • data:image/svg+xml,<SVG>[NOT_ENCODED_SVGFILECONTENT</SVG>

Read more here:

Xamarin.Forms

It's very easy, just add Xamarin.FFImageLoading.Svg.Forms nuget and use SvgCachedImage instead CachedImage. To avoid linking issues (type not found exceptions), please reference SvgCachedImage in platform specific project:

    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();

            CachedImageRenderer.Init();
            var ignore = typeof(SvgCachedImage);
            LoadApplication(new App());

            return base.FinishedLaunching(app, options);
        }
    }
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="FFImageLoading.Forms.Sample.SvgSamplePage"
		xmlns:ffimageloadingsvg="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms">

	<ContentPage.Content>
		<ffimageloadingsvg:SvgCachedImage WidthRequest="200" HeightRequest="200" Source="sample.svg"/>	

		<!-- SECOND APPROACH (PCL EmbeddedResource): -->
		<ffimageloadingsvg:SvgCachedImage WidthRequest="200" HeightRequest="200" Source="resource://FFImageLoading.Forms.Sample.Resources.sample.svg"/>  
            
	</ContentPage.Content>
</ContentPage>

When loading from embedded resources, you can specify different assembly with following format: resource://FFImageLoading.Forms.Sample.Resources.sample.svg?assembly=[ASSEMBLY FULL NAME]

https://stackoverflow.com/questions/658446/how-do-i-find-the-fully-qualified-name-of-an-assembly

More advanced scenarios: use a custom SvgImageSource which enables SVG support. Please notice, that it has optional parameters for controlling renderered SVG size (automatic by default) IMPORTANT: Your projects also must reference System.Xml.Linq.

From code:

source = SvgImageSource.FromFile("image.svg")
source = SvgImageSource.FromUri("http://example.com/image.svg")
// etc...

Or use a provided converter (eg. when using XAML):

Source="{Binding SvgFileName, Converter={StaticResource SvgImageSourceConverter}}"

Xamarin Native

Add Xamarin.FFImageLoading.Svg nuget package to platform project. Use ImageService with svg data resolver for displaying svg images. See below in the Android section for details.

On Xamarin UWP, in Release mode with .NET Native compilation activated, the function SvgImageSource::FromResource() will not work for auto-detecting the calling assembly. You need to pass the assembly containing the resources as a parameter.

GetCallingAssembly() does not work because System.Reflection is altered by the Native compilation.

// example of solution: using System.Reflection; // [...] if (Runtime.IsUWP()) { // this fixes the bug that GetCallingAssembly() throws an exception in Release mode for UWP Assembly sourceAssembly = typeof(CurrentClassNameWithResourcesInSameAssembly).GetTypeInfo().Assembly; return SvgImageSource.FromResource(resourcePath, sourceAssembly); }

Xamarin.Android

When loading images you have to configure custom data resolver which enables SVG support:

ImageService.Instance
		.LoadFile("image.svg")
		.LoadingPlaceholder("placeholder.svg")
		.WithCustomDataResolver(new SvgDataResolver(200, 0, true))
		.WithCustomLoadingPlaceholderDataResolver(new SvgDataResolver(200, 0, true))
		.Into(imageView);

In xaml markup it's just simple ImageView:

	<ImageView
		android:id="@+id/image_view"
		android:layout_width="match_parent"
		android:layout_height="match_parent"/>

You can also load svg image from string:

	var svgString = @"<svg><rect width=""30"" height=""30"" style=""fill:blue"" /></svg>";

	ImageService.Instance
		.LoadString(svgString)
		.LoadingPlaceholder(placeHolderPath)
		.WithCustomDataResolver(new SvgDataResolver(64, 0, true))
		.WithCustomLoadingPlaceholderDataResolver(new SvgDataResolver(64, 0, true))
		.Into(imageView);

or from URL:

	ImageService.Instance
		.LoadUrl("https://images/image.svg")
		.WithCustomDataResolver(new SvgDataResolver(64, 0, true))
		.Into(imageView);

Xamarin.iOS

Converting svg string into UIImage:

	var svgString = @"<svg><rect width=""30"" height=""30"" style=""fill:blue"" /></svg>";

	UIImage img = await ImageService.Instance
		.LoadString(svgString)
		.WithCustomDataResolver(new SvgDataResolver(64, 0, true))
		.AsUIImageAsync();

SVG string replacement (including colors)

  • You can replace svg string by using Dictionary<string, string> replacement map.
  • You can use Regex.Replace, just set dictionary item key to: regex:[your regex expression here]

Xamarin.Forms

Specify / bind ReplaceStringMap parameter of SvgCachedImage object OR provide optional replaceStringMap parameter in SvgImageSource methods.

Native

Provide replaceStringMap parameter in SvgDataResolver constructor.

Example replacing fill color

Before creating a ReplaceStringMap, always check the SVG for how the structure is. For example they might use the "fill=" attribute or the CSS style "style="fill: rgb(0, 0, 0);" in it. The replace the latter, please see the code below as an exampe. Setting the ReplaceStringMap property automatically refreshes the image if you want to change colors dynamically.

var dict = new Dictionary<string, string>();
dict.Add("fill: rgb(0, 0, 0);", GetRGBFill(myXamarinColor));

var icon = new SvgCachedImage
{
     ReplaceStringMap = dict,
     Source = source,
};

And a small helper to do the replacement:

public static string GetRGBFill(Xamarin.Forms.Color color)
{
     var red = (int)(color.R * 255);
     var green = (int)(color.G * 255);
     var blue = (int)(color.B * 255);
     var rgbFill = $"fill: rgb({red},{green},{blue});";
     return rgbFill;
}