在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
相关产品推荐
相关产品推荐

