Ffimageloading: Change the color of an SVG?

Created on 16 Jun 2017  路  15Comments  路  Source: luberda-molinet/FFImageLoading

I am fully aware on how the fill attribute on the path tag changes color but i want to change it via the xaml tag. Is this support coming out soon?



width="22px" height="22px" viewBox="0 0 22 22" enable-background="new 0 0 22 22" xml:space="preserve">
check-circle-2





SVG question

Most helpful comment

I change color of a SVG from XAML like this

<ffsvg:SvgCachedImage WidthRequest="40" HeightRequest="40" HorizontalOptions="Center" Source="resource://JCabinet.Resources.Icons.qrscan.svg"> <ffimg:CachedImage.Transformations> <fftransf:TintTransformation HexColor="#ff000000" EnableSolidColor="true"/> </ffimg:CachedImage.Transformations> </ffsvg:SvgCachedImage>

All 15 comments

Replacing parts of SVG's is already supported in latest prerelease. You just define a replacement map dictionary (Dictionary<string, string>).

  • SvgDataResolver: constructor's replaceStringMap parameter
  • SvgImageSource: constructor's replaceStringMap parameter
  • SvgCachedImage: ReplaceStringMap property

But there isn't a way to change it via the XAML?

could you give an example of these @daniel-luberda ?

Yes, an example would be neat. :3

I change color of a SVG from XAML like this

<ffsvg:SvgCachedImage WidthRequest="40" HeightRequest="40" HorizontalOptions="Center" Source="resource://JCabinet.Resources.Icons.qrscan.svg"> <ffimg:CachedImage.Transformations> <fftransf:TintTransformation HexColor="#ff000000" EnableSolidColor="true"/> </ffimg:CachedImage.Transformations> </ffsvg:SvgCachedImage>

There are many ways to achieve it.

  • You can just define Dictionary<string,string> with needed key/value items inside ResourceDictionary.
  • You can create a static Dictionary<string,string> and combine it with x:Static
  • You can create a custom IValueConverter which will parse string and return a Dictionary<string,string>
  • etc

Did you try it?

@daniel-luberda : There is no ReplaceStringMap property available on SvgCachedImage. I am on the latest prerelease 2.2.10-pre-438. Currently going with solution @vlkam provided..

Is there an example of Xamarin Forms code or XAML?

An example here would indeed be nice.

I'm geting nowhere with a simple SVG that I want to present as white strokes on a black background.

vlkam's XAML example above is not helping. HexColor="#FFFFFFFF" just gives me one white box.

Since everyone needs an example, I'll give you guys one :)
So first we create a Dictionary in our ViewModel and we get the Color we want from our ResourceDictionary.
public Dictionary<string, string> ReplaceMap { get; set; }
public Color CircleColor = (Color)Application.Current.Resources["COLOR_YOU_WANT"];
Then in the Contructor of our ViewModel we construct the Dictionary
ReplaceMap = new Dictionary<string, string>() { {"#FILLCOLOR", GetHexString(CircleColor) } };
I've used a method to Convert the color we got from our ResourceDictionary to a HexString, because getting the color as we did gives back a Color object which cannot be inserted into the SVG.
HexString method(I took this from StackOverflow somwhere):

public static string GetHexString(Xamarin.Forms.Color color)
{
var red = (int)(color.R * 255);
var green = (int)(color.G * 255);
var blue = (int)(color.B * 255);
var alpha = (int)(color.A * 255);
var hex = $"#{alpha:X2}{red:X2}{green:X2}{blue:X2}";

        return hex;
    }

Now set the Binding of ReplaceMapString to ReplaceMap in your View.xaml and run it.

Here is another example. Always check your SVG how the colors are inserted, I use Icons8 for example for my SVG icons and they generate files with "style="fill: rgb(0, 0, 0);" in it. I personally always use black as default so you can see them in the file explorer in Windows (https://code.google.com/archive/p/svg-explorer-extension/downloads).

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;
}

@Sokoo92 @rogihee

Feel free to update our wiki with samples, it could help others to see it.

@daniel-luberda done

@daniel-luberda How do you set the HexColor using a style?
I tried this but it doesn't work (since HexColor is a string I tried it this way).

In my ResourceDictionary:

<Color x:Key="iconColor_light" x:FactoryMethod="FromHex">
        <x:Arguments>
            <x:String>#000000</x:String>
        </x:Arguments>
</Color>

<Color x:Key="iconColor_dark" x:FactoryMethod="FromHex">
        <x:Arguments>
            <x:String>#ffffff</x:String>
        </x:Arguments>
</Color>

And then in XAML:

<ffimageloadingsvg:SvgCachedImage.Transformations>
    <ffimageloadingTrans:TintTransformation HexColor="{AppThemeBinding Light={StaticResource iconColor_light},
        Dark={StaticResource iconColor_dark}}" EnableSolidColor="true" />
</ffimageloadingsvg:SvgCachedImage.Transformations>

Is it even possible to bind it to the AppTheme?

@stesvis looking at the source its probably not possible to bind this value to an app theme.

I came up with a hack that will work for the current theme of the app, so long as the OSAppTheme is never changed at runtime, you won't have any worries:

  1. Reference your SvgCachedImage
<ff:SvgCachedImage x:Name="SvgImage" Source="{x:Static resources:SvgConstants.SwipeRightIcon}"/>
  1. Add the following method:
private void SetTint(OSAppTheme theme)
{
    string hexColor = string.Empty;

    switch (theme)
    {
        case OSAppTheme.Light:
            hexColor = "#3497c5";
            break;

        case OSAppTheme.Dark:
            hexColor = "#ed625c";
            break;
    }

    var tint = new TintTransformation()
    {
        HexColor = hexColor,
        EnableSolidColor = true
    };

    SvgImage.Transformations.Add(tint);
}
  1. Call the method with the current app theme
public YourPage()
{
    InitializeComponent();

    SetTint(Application.Current.RequestedTheme);
}

As I said, this won't bind at runtime because the library itself is not doing that. However its a nice enough workaround to at least apply a theme specific tint!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

matheusvelloso picture matheusvelloso  路  4Comments

dkornev picture dkornev  路  4Comments

angelru picture angelru  路  4Comments

lhughey picture lhughey  路  3Comments

thisisthekap picture thisisthekap  路  5Comments