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

MAUI迁移:Android端SVG资源如何转为流用于SkiaSharp绘制?

解决MAUI迁移中Android端内置SVG资源转SkiaSharp可用格式的问题

问题根源

iOS打包时会将SVG资源转为PNG并存放在包根目录,因此可以通过FileSystem.OpenAppPackageFileAsync直接获取流;而Android会按屏幕分辨率将图片拆分到/res/drawable-*目录,无法通过文件系统路径访问,只能通过资源ID加载原生Drawable,但Drawable无法直接用于SkiaSharp绘制。

解决方案:将Android Drawable转为SKBitmap

核心思路是把Android原生Drawable(包括BitmapDrawable和VectorDrawable)转换为SkiaSharp的SKBitmap,这样就能直接在SKCanvas上绘制。

1. 跨平台工具类封装

using SkiaSharp;
#if ANDROID
using Android.Graphics;
using Android.Content.Res;
#endif

public static class ResourceBitmapHelper
{
    public static async Task<SKBitmap> GetBuiltInSKBitmapAsync(string resourceName)
    {
#if IOS
        // iOS端通过文件系统加载PNG并解码为SKBitmap
        using var stream = await FileSystem.OpenAppPackageFileAsync($"{resourceName}.png");
        return stream != null ? SKBitmap.Decode(stream) : null;
#elif ANDROID
        // 从资源名获取对应的Android资源ID
        var resourceId = MainApplication.Current.Resources.GetIdentifier(
            resourceName, 
            "drawable", 
            MainApplication.Current.PackageName
        );
        if (resourceId == 0) return null;

        var drawable = MainApplication.Current.GetDrawable(resourceId);
        if (drawable == null) return null;

        Bitmap androidBitmap;
        // 处理矢量Drawable和普通BitmapDrawable
        if (drawable is VectorDrawable vectorDrawable)
        {
            // 创建空白Bitmap并将VectorDrawable绘制到上面
            androidBitmap = Bitmap.CreateBitmap(
                vectorDrawable.IntrinsicWidth, 
                vectorDrawable.IntrinsicHeight, 
                Bitmap.Config.Argb8888
            );
            using var canvas = new Canvas(androidBitmap);
            vectorDrawable.SetBounds(0, 0, canvas.Width, canvas.Height);
            vectorDrawable.Draw(canvas);
        }
        else
        {
            androidBitmap = ((BitmapDrawable)drawable).Bitmap;
        }

        // 将Android Bitmap转为SKBitmap
        var skBitmap = androidBitmap.ToSKBitmap();
        androidBitmap.Recycle(); // 释放原生Bitmap资源,避免内存泄漏
        return skBitmap;
#else
        return null;
#endif
    }
}

2. 使用示例

在SkiaSharp绘制逻辑中调用工具类,直接获取可用的SKBitmap:

// 替换为你的内置资源名称(不带后缀)
var skBitmap = await ResourceBitmapHelper.GetBuiltInSKBitmapAsync("icon_svg");
if (skBitmap != null)
{
    // 在SKCanvas上绘制图片
    canvas.DrawBitmap(skBitmap, new SKPoint(100, 100), new SKPaint());
}

注意事项

  • Android端需要确保资源名称与Resources/drawable目录下的文件名称一致(不含后缀)
  • 处理VectorDrawable时要注意创建对应尺寸的Bitmap,避免拉伸变形
  • 转换后记得调用androidBitmap.Recycle()释放原生资源,防止内存占用过高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:20:43