SkiaSharp Canvas绘制文本不显示问题求助
SkiaSharp绘制文本在using块释放流后不显示的解决方案
这个问题我之前也踩过坑,核心原因在于SkiaSharp的SKTypeface.FromStream并不会直接复制字体数据到内存——它只是持有一个对传入流的引用,依赖流始终处于可用状态来读取字体信息。当你用using块释放流后,SKTypeface就失去了字体数据的来源,导致SKPaint的FontMetrics、FontSpacing等属性失效,最终无法绘制文本。
下面给你两种可靠的解决办法:
方案一:用SKData将字体加载到内存(推荐)
把流的内容读取到SKData中,让SKTypeface基于内存中的字体数据创建,这样即使原流被释放,也不会影响Typeface的正常使用:
SKPaint _paint = new SKPaint(); // 记得设置文本大小,默认TextSize可能为0,也会导致不显示 _paint.TextSize = 48; using(Stream stream = _assembly.GetManifestResourceStream(fontPath)) { if (stream == null) { // 这里可以加资源不存在的异常处理 throw new FileNotFoundException("字体资源未找到", fontPath); } // 将流内容复制到内存SKData中 using(var fontData = SKData.Create(stream)) { _paint.Typeface = SKTypeface.FromData(fontData); } } canvas.DrawText("12345", X, Y, _paint);
SKData会把流的全部内容缓存到内存缓冲区,SKTypeface.FromData创建的Typeface完全独立于原流,后续流释放也不会影响字体的使用,这是最安全的方式。
方案二:手动管理流的生命周期(不推荐)
如果你坚持使用SKTypeface.FromStream,可以去掉using块,在完成所有文本绘制操作后再手动释放流。但这种方式要特别注意内存泄漏问题,必须确保流最终被释放:
SKPaint _paint = new SKPaint(); _paint.TextSize = 48; Stream stream = null; try { stream = _assembly.GetManifestResourceStream(fontPath); _paint.Typeface = SKTypeface.FromStream(stream); canvas.DrawText("12345", X, Y, _paint); } finally { // 确保流最终被释放 stream?.Dispose(); }
这种方式风险较高,一旦代码分支遗漏了流的释放,就会造成内存泄漏,所以优先推荐方案一。
另外还要注意两个细节:
- 确认
fontPath是正确的嵌入资源路径(比如命名空间+资源文件名),避免流加载失败导致Typeface为null; - 务必设置
SKPaint.TextSize属性,默认值为0的话,即使Typeface正常,也会绘制出看不见的文本。
内容的提问来源于stack exchange,提问作者Han Nhu Thien
相关产品推荐
相关产品推荐

