Flutter PDF包iOS端TooManyPagesException异常求助
问题详情
在使用pdf包生成PDF时,仅iOS端出现异常,Android端运行正常:
- 初始问题:Widget高度(823.408)超过页面高度(728.5039370078739),提示需使用SpanningWidget或单页布局;
- 改用Wrap组件(SpanningWidget的一种)包裹内容后,抛出新的异常,错误栈如下:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Instance of 'TooManyPagesException' #0 MultiPage.generate (package:pdf/src/widgets/multi_page.dart:251:9) #1 Document.addPage (package:pdf/src/widgets/document.dart:117:10) #2 _QuillPageState.generatePdf (package:daiaryapp/pages/addDairyPage/quill_page.dart:76:9)
#3 _QuillPageState.build. . (package:daiaryapp/pages/addDairyPage/quill_page.dart:320:48)
相关代码:
pdf.addPage(pw.MultiPage( build: (pw.Context context) { final content = <pw.Widget>[]; content.add( pw.Center( child: pw.Text( post.dairyName.toString(), // Replace with your desired title style: customTitle, ), ), ); int itemsPerPage = 8; for (var i = 0; i < deltaData['ops'].length; i++) { final op = deltaData['ops'][i]; if (op.containsKey('insert')) { if (op['insert'] is String) { final lines = (op['insert'] as String).split('-'); for (var line in lines) { final textWidget = pw.Padding( padding: pw.EdgeInsets.all(1.0), child: pw.Text( line.trim(), // Trim to remove extra spaces style: customTextStyle, // Apply custom text style here ), ); content.add(textWidget); } } else if (op['insert'] is Map && op['insert'].containsKey('image')) { final imageData = op['insert']['image'].split(',')[1]; final Uint8List decodedImage = base64Decode(imageData); final imageWidget = pw.Padding( padding: pw.EdgeInsets.all(1.0), child: pw.Image( pw.MemoryImage( decodedImage, ), fit: pw.BoxFit.cover, height: 245.0, ), ); content.add(imageWidget); } } if (i > 0 && (i + 1) % itemsPerPage == 0) { content.add(pw.Container(width: 1.0, height: 1.0)); } } // return content; return [ pw.Wrap( children: content, ), ]; }, ));
解决方案
方案1:移除Wrap,利用MultiPage自动分页能力
Wrap组件会打乱MultiPage的分页逻辑,导致无法合理拆分内容,直接返回内容列表即可:
- 取消Wrap包裹,直接返回
content; - 移除手动添加的空
Container,避免干扰分页计算; - 图片不要固定高度,改为根据页面宽度自适应,避免单页高度溢出:
pw.Image( pw.MemoryImage(decodedImage), fit: pw.BoxFit.fitWidth, width: context.pageFormat.availableWidth, )
方案2:显式指定页面格式并设置分页上限
iOS端默认页面格式可能与Android存在差异,同时设置maxPages避免无限分页:
pdf.addPage(pw.MultiPage( pageFormat: pw.PageFormat.a4, // 统一使用A4尺寸 maxPages: 100, // 根据业务需求设置合理上限 build: (pw.Context context) { // 原有内容逻辑... return content; }, ));
方案3:改用SinglePage(业务允许单页展示时)
如果业务不需要分页,可使用SinglePage并开启裁剪处理溢出内容:
pdf.addPage(pw.SinglePage( clip: true, build: (pw.Context context) { // 原有内容逻辑... return pw.Column(children: content); }, ));
总结
优先尝试方案1,移除Wrap和空Container,让MultiPage自动处理分页,同时自适应图片尺寸,这是解决此类跨端分页异常最直接的方式。若仍有问题,再通过调整页面格式或分页上限进一步排查。
内容的提问来源于stack exchange,提问作者Muhammad Naseer

