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

在Xamarin Forms中使用SkiaSharp加载自定义字体的问题

在Xamarin.Forms中通过SkiaSharp使用自定义字体的正确姿势

你遇到的问题其实挺常见的——直接用SKTypeface.FromFamilyName或FromFile确实容易踩坑,因为Xamarin.Forms的资源管理逻辑和SkiaSharp的文件读取规则不是直接对接的,下面给你一步步拆解正确的实现方式:

第一步:先把字体文件正确嵌入各平台项目

首先得确保你的CoText_Bd.ttf(假设是ttf格式)在每个平台的项目里都放对位置,并且设置了正确的生成操作:

  • Android:把字体文件放到Assets文件夹,右键文件设置生成操作为AndroidAsset
  • iOS:放到Resources文件夹,设置生成操作为BundleResource,还要在Info.plist里添加字体声明:
    <key>UIAppFonts</key>
    <array>
      <string>CoText_Bd.ttf</string>
    </array>
    
  • UWP:放到Assets文件夹,设置生成操作为Content

第二步:用依赖服务获取字体字节流(核心解决思路)

跨平台下直接用文件名读取字体肯定会失败,因为不同平台的资源路径规则不一样。最可靠的方式是通过依赖服务把字体文件读成字节数组,再传给SkiaSharp创建字体:

1. 在共享项目定义接口

先写一个统一的接口,让各平台实现字体读取逻辑:

public interface IFontService
{
    byte[] GetFontBytes(string fontFileName);
}

2. 各平台实现依赖服务

Android平台实现:

[assembly: Dependency(typeof(FontServiceAndroid))]
namespace YourAppName.Droid
{
    public class FontServiceAndroid : IFontService
    {
        public byte[] GetFontBytes(string fontFileName)
        {
            using (var stream = Android.App.Application.Context.Assets.Open(fontFileName))
            {
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, (int)stream.Length);
                return bytes;
            }
        }
    }
}

iOS平台实现:

[assembly: Dependency(typeof(FontServiceiOS))]
namespace YourAppName.iOS
{
    public class FontServiceiOS : IFontService
    {
        public byte[] GetFontBytes(string fontFileName)
        {
            var path = NSBundle.MainBundle.PathForResource(Path.GetFileNameWithoutExtension(fontFileName), Path.GetExtension(fontFileName));
            return File.ReadAllBytes(path);
        }
    }
}

UWP平台实现:

[assembly: Dependency(typeof(FontServiceUWP))]
namespace YourAppName.UWP
{
    public class FontServiceUWP : IFontService
    {
        public byte[] GetFontBytes(string fontFileName)
        {
            var file = Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/{fontFileName}")).GetAwaiter().GetResult();
            using (var stream = file.OpenStreamForReadAsync().GetAwaiter().GetResult())
            {
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, (int)stream.Length);
                return bytes;
            }
        }
    }
}

第三步:在SkiaSharp中加载字体

现在回到共享项目的SkiaSharp绘制逻辑里,通过依赖服务拿到字体字节,再创建SKTypeface:

var fontBytes = DependencyService.Get<IFontService>().GetFontBytes("CoText_Bd.ttf");
using (var typeface = SKTypeface.FromData(SKData.Create(fontBytes)))
{
    paint.Typeface = typeface;
    // 这里写你的文本绘制逻辑
}

为什么你的原代码不生效?

  • SKTypeface.FromFamilyName("CoText_Bd"):这个方法是找系统已安装的字体,你的自定义字体是嵌入到项目里的,系统没安装,所以根本找不到
  • SKTypeface.FromFile("CoText_Bd"):跨平台下的资源路径不是简单的文件名,Android的Assets、iOS的Bundle都不是普通的文件系统路径,自然读取失败

按上面的步骤操作,就能在所有平台正常加载自定义字体了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:51:05