You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Maui中如何显示下载后的SVG图片?

.NET MAUI 本地/URL加载SVG显示解决方案

问题背景

我们的应用中SVG图片分两类:

  • 嵌入资源的SVG:通过转换器修改扩展名为.png即可正常显示
  • RestService加载的SVG(用户可自行添加命名):从URL、Microsoft.Maui.Storage.FileSystem.AppDataDirectory或Environment.SpecialFolder.LocalApplicationData路径加载时,无论是直接用.svg扩展名还是转.png都无法显示。之前Xamarin.Forms用FFImageLoading实现,迁移到.NET MAUI后找不到合适方案。

现有代码

下载SVG文件代码

private async Task DownloadIcons(List<DownloadIcon> downloadIcons)
{
    var lightIconsFolderPath = Path.Combine(iconFolderPath, lightIconFolderName);
    var darkIconsFolderPath = Path.Combine(iconFolderPath, darkIconFolderName);

    DirectoryManager(lightIconsFolderPath);
    DirectoryManager(darkIconsFolderPath);

    CurrentIcons = new List<Icon>();

    foreach (var downloadIcon in downloadIcons)
    {
        Icon icon = new Icon();
        icon.IconId = downloadIcon.IconId;

        var ligthIconBytes = await DownloadIconFromURL(downloadIcon.LightThemeIconLink);
        icon.LightThemeIconPath = await WriteIconToDisk(lightIconsFolderPath, ligthIconBytes, downloadIcon.IconTranslations[0].Name);
        
        var darkIconBytes = await DownloadIconFromURL(downloadIcon.DarkThemeIconLink);
        icon.DarkThemeIconPath = await WriteIconToDisk(darkIconsFolderPath, darkIconBytes, downloadIcon.IconTranslations[0].Name);
        

        CurrentIcons.Add(icon);
    }
}       

private async Task<byte[]> DownloadIconFromURL(string downloadedIconUrl)
{
    try
    {
        byte[] bytes;
        using (HttpClient httpClient = new HttpClient())
        {
            bytes = await httpClient.GetByteArrayAsync(downloadedIconUrl);
        }
        
        return bytes;
    }
    catch (System.Exception e)
    {
        log.Error("Exception while trying to download icon from url", e);
        return null;
    }
}

写入磁盘代码

private async Task<string> WriteIconToDisk(string pathToIconsFolder, byte[] iconBytes, string iconName)
{
    try
    {
        string fileName = "";
        string namingConventionName = ModifyLowerCaseLetterString(iconName);
       
        fileName = Path.Combine(pathToIconsFolder, $"{namingConventionName}.svg");
        File.WriteAllBytes(fileName, iconBytes);
        return fileName;
    }
    catch (System.Exception e)
    {
        log.Error("Exception while trying to write icon on device", e);
        return null;
    }
}

XAML图片控件

<Image HeightRequest="24" Source="{Binding Icon.ActiveIconPath, Converter={StaticResource SvgImageSourceConverter}}"
        WidthRequest="24" />

转换器处理后路径示例:/storage/emulated/0/Android/data/[company]/files/icons/light/light.png,尝试.svg扩展名也无法显示。

解决方案

方案1:使用FFImageLoading.Maui(原库迁移版)

  1. 安装NuGet包:FFImageLoading.Maui及FFImageLoading.Svg.Maui
  2. 初始化配置:在MauiProgram.cs中添加:
builder.UseFFImageLoading();
builder.ConfigureFFImageLoading(options =>
{
    options.SkipMemoryCache = false;
    options.DiskCacheDuration = TimeSpan.FromDays(30);
});
  1. 替换XAML控件:用CachedImage替代原生Image,并指定SVG解码:
<ffimageloading:CachedImage HeightRequest="24" WidthRequest="24"
                            Source="{Binding Icon.ActiveIconPath}"
                            DownsampleToViewSize="True">
    <ffimageloading:CachedImage.Transformations>
        <fftransformations:SvgTransformation />
    </ffimageloading:CachedImage.Transformations>
</ffimageloading:CachedImage>

无需再修改扩展名,直接传入.svg路径即可,支持本地文件、URL、嵌入资源。

方案2:使用SkiaSharp.Svg手动渲染

  1. 安装NuGet包:SkiaSharp.Views.Maui和SkiaSharp.Svg
  2. 自定义转换器:创建SvgToImageSourceConverter,将SVG文件转为ImageSource:
public class SvgToImageSourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string path && File.Exists(path))
        {
            using var svg = new SKSvg();
            svg.Load(path);
            
            var bitmap = new SKBitmap((int)svg.CanvasSize.Width, (int)svg.CanvasSize.Height);
            using var canvas = new SKCanvas(bitmap);
            canvas.Clear(SKColors.Transparent);
            canvas.DrawPicture(svg.Picture);
            
            return ImageSource.FromStream(() =>
            {
                var stream = new MemoryStream();
                bitmap.Encode(stream, SKEncodedImageFormat.Png, 100);
                stream.Position = 0;
                return stream;
            });
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
  1. XAML中使用:保持原有Image控件,替换转换器为自定义的SvgToImageSourceConverter,传入.svg路径即可。

注意事项

  • 若使用FFImageLoading,需确保权限配置正确(如Android的网络权限、文件读取权限)
  • SkiaSharp方案可根据View尺寸调整SVG渲染大小,适配不同显示需求

内容的提问来源于stack exchange,提问作者KarsaOrlong1981

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:20:50