1

I want to use SVG images as icons on a TabbedPage in Xamarin.Forms for iOS.

The documentation for the TabbedPage class provides the following tip:

The TabbedRenderer for iOS has an overridable GetIcon method that can be used to load tab icons from a specified source. This override makes it possible to use SVG images as icons on a TabbedPage. In addition, selected and unselected versions of an icon can be provided.

I created the following class to perform the override:

[assembly: ExportRenderer(typeof(TabsRoot), typeof(TabbedPageCustomRenderer))]
namespace MyProject.iOS.Renderers
{
    public class TabbedPageCustomRenderer : TabbedRenderer
    {
        protected override Task<Tuple<UIImage, UIImage>> GetIcon(Page page)
        {
            var image = UIImage.FromFile(@"home-black-18dp.svg");
            return Task.FromResult(new Tuple<UIImage, UIImage>(image, image));
        }
    }
}

The accepted answer in this thread recommends creating a UIImage from an SVG file by doing something like this: var myImage = UIImage.FromFile(<<file name>>) where <<filename>> is an SVG. This other thread contradicts the previous thread, saying that UIImages cannot be made from SVG files. Sure enough, when I provide an SVG file, UIImage.FromFile() returns null and no icon is shown at all, just as the latter thread predicted. When I provide a PNG file, the override works as expected.

Another way I've tried to square this circle is to use the SvgCachedImage provided by FFImageLoading.Svg.Forms, but I haven't figured out how to 'wrap' a UIImage around an SvgCachedImage or whether that is even appropriate in this case.

Thank you for your help!

1 Answers1

0

Add Xamarin.FFImageLoading.Svg nuget package to your ios project.

then create the UImage in your GetIcon method like below :

UIImage img = await ImageService.Instance
    .LoadFile("timer.svg")
    .WithCustomDataResolver(new SvgDataResolver((int)(TabBar?.Bounds.Height / 2 ?? 30), (int)(TabBar?.Bounds.Height / 2 ?? 30), false))
    .AsUIImageAsync();
UIImage newImg = img.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
Leo Zhu
  • 15,726
  • 1
  • 7
  • 23
  • That's a really cool method for rasterizing an SVG input, but I'l like to display a true SVG without any pixelation / rasterization. – Dallin Jackson Jul 25 '20 at 20:02
  • Maybe you could refer to [this](https://stackoverflow.com/a/58906958/10768653). – Leo Zhu Jul 28 '20 at 07:33
  • Thanks. Do you mean to suggest that I should forego the SVG route and instead use rasterized icons? If so, do you know of a way to "scale" the rasterized graphics in my renderer above (i.e. increase dpi) so that there isn't any obvious pixelation in the displayed icons? My ultimate goal is to minimize pixelation; I'm less concerned about the particular image type, whether it's SVG, PNG, or something else. Thanks again for your help. – Dallin Jackson Jul 28 '20 at 22:27
  • I think if you use the icon as tabbedpage icon,neither PNG nor SVG has much impact. – Leo Zhu Jul 29 '20 at 02:11