解决pdf.dart包fontFallback的Future问题,实现Emoji与特殊字符打印
解决方案
问题核心
你的代码存在两个关键问题:
fontFallback需要接收已加载完成的PdfFont实例列表,但你直接传入了返回Future的异步方法emoji()- 未指定支持法语特殊字符的主字体,可能导致
Œ这类字符显示异常
正确实现代码
1. 提前预加载字体
先异步加载支持法语的主字体和Emoji fallback字体,确保在构建PDF Widget前字体已准备好:
import 'package:google_fonts/google_fonts.dart'; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; import 'dart:typed_data'; // 全局存储预加载的字体(也可使用状态管理类替代全局变量) pw.PdfFont? _mainFont; pw.PdfFont? _emojiFont; // 预加载字体方法 Future<void> _preloadFonts() async { // 选择支持法语特殊字符的主字体(如Roboto、Noto Sans) _mainFont = await PdfGoogleFonts.roboto(); // 加载彩色Emoji字体 _emojiFont = await PdfGoogleFonts.notoColorEmoji(); }
2. 修改Cell构建方法
使用预加载完成的字体,配置fontFallback处理Emoji:
static pw.Widget cell(pw.Context context, int index) { String texte = SQLHelper.listeItemsRepas()[index]; // 确保字体已加载完成(开发环境下用assert检查,生产环境可加兜底逻辑) assert(_mainFont != null && _emojiFont != null, "请先调用_preloadFonts加载字体"); final textStyle = pw.TextStyle( font: _mainFont!, fontSize: 9, // fontFallback是列表,可添加多个备用字体 fontFallback: [_emojiFont!], ); return pw.Container( constraints: const pw.BoxConstraints.tightFor(width: double.infinity, height: 22.0), padding: const pw.EdgeInsets.all(3), child: pw.Text( texte, style: textStyle, textAlign: pw.TextAlign.left, softWrap: true, maxLines: 6, ), ); }
3. 生成PDF时先加载字体
在生成PDF文档的主流程中,先执行字体预加载:
Future<Uint8List> generatePdfDocument() async { // 先加载字体 await _preloadFonts(); final pdf = pw.Document(); pdf.addPage( pw.Page( build: (context) { return pw.ListView.builder( itemCount: SQLHelper.listeItemsRepas().length, itemBuilder: cell, ); }, ), ); return pdf.save(); }
关键说明
- 主字体必须选择包含法语特殊字符的字体(Google Fonts中的Roboto、Noto Sans等都支持)
fontFallback是已加载字体的列表,不能直接传入Future,必须等待异步加载完成后再使用- 若不想用全局变量,可通过状态管理(如Provider、Riverpod)传递已加载的字体实例
内容的提问来源于stack exchange,提问作者PiPaddy
相关产品推荐
相关产品推荐

