如何在Flutter PDF中让表格填充页面剩余空白区域?
Flutter PDF 实现表格填充页面剩余空白
核心思路:要让表格填满页面剩余空白,关键是让表格总高度撑满可用空间,以下是两种可行方案:
方案一:补充空行至填满页面(适配现有Table.fromTextArray代码)
通过计算页面剩余可容纳的行数,给数据列表补充对应数量的空行,让表格自动撑满空间。
实现步骤:
- 计算页面可用高度:减去页眉、页脚、表格标题等固定元素的高度,得到表格可占用的总高度。
- 计算单条数据行的高度:根据字体大小、行间距估算(或通过测量文本高度精确计算)。
- 计算需要补充的空行数:用总可用高度除以单行高度,得到总需行数,减去已有数据行数即为需要补充的空行数。
- 将空行(各列均为空文本的列表)追加到数据列表中。
修改后的代码:
pw.Widget buildTableForSales(List<dynamic> itemData) { // 1. 定义基础参数(根据实际纸张/布局调整) final double pageHeight = 842; // A4纸高度(pt单位) final double headerFooterHeight = 100; // 页眉+页脚总高度 final double tableHeaderHeight = 20; // 表格标题行高度 final double rowHeight = 18; // 单条数据行高度(根据字体大小调整) // 2. 计算可用高度和需要补充的空行数 final double availableHeight = pageHeight - headerFooterHeight - tableHeaderHeight; final int totalNeededRows = (availableHeight / rowHeight).floor(); final int emptyRowsNeeded = totalNeededRows - itemData.length; // 3. 生成空行数据(与表头列数一致的空文本) final List<List<pw.Widget>> emptyRows = List.generate( emptyRowsNeeded > 0 ? emptyRowsNeeded : 0, (_) => List.generate(9, (_) => pw.Text("")), ); // 4. 合并原有数据和空行 final List<List<pw.Widget>> fullData = [...itemData, ...emptyRows]; return pw.Table.fromTextArray( tableWidth: pw.TableWidth.max, headers: [ pw.Text("SL NO", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("Item Code", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("Description", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("UNIT", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("QTY", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("Rate", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("Total Amt", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("VAT Amt", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("Net Amt", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), ], cellAlignments: { 0: pw.Alignment.center, 1: pw.Alignment.topLeft, 2: pw.Alignment.topLeft, 3: pw.Alignment.topRight, 4: pw.Alignment.topRight, 5: pw.Alignment.topRight, 6: pw.Alignment.topRight, 7: pw.Alignment.topRight, }, cellStyle: const pw.TextStyle(fontSize: 10), headerDecoration: const pw.BoxDecoration( border: pw.TableBorder(bottom: pw.BorderSide(color: PdfColors.black, width: 1.5)), ), border: const pw.TableBorder( horizontalInside: pw.BorderSide(width: 0, color: PdfColors.white), verticalInside: pw.BorderSide(color: PdfColors.black), top: pw.BorderSide(color: PdfColors.black), left: pw.BorderSide(color: PdfColors.black), right: pw.BorderSide(color: PdfColors.black), bottom: pw.BorderSide(color: PdfColors.black), ), data: fullData, ); }
方案二:自定义Table组件(更灵活的高度控制)
放弃Table.fromTextArray的封装,直接使用pw.Table,通过pw.Expanded让表格撑满剩余垂直空间。
实现思路:
- 用
pw.Column包裹表格,将表格放在pw.Expanded中,让其占满剩余垂直空间。 - 自定义表格行,对于数据行和填充行设置统一的布局规则,确保总高度撑满。
示例代码片段:
pw.Widget buildCustomTable(List<dynamic> itemData) { return pw.Expanded( child: pw.Table( tableWidth: pw.TableWidth.max, border: const pw.TableBorder( verticalInside: pw.BorderSide(color: PdfColors.black), top: pw.BorderSide(color: PdfColors.black), left: pw.BorderSide(color: PdfColors.black), right: pw.BorderSide(color: PdfColors.black), bottom: pw.BorderSide(color: PdfColors.black), ), children: [ // 表头行 pw.TableRow( decoration: const pw.BoxDecoration( border: pw.TableBorder(bottom: pw.BorderSide(color: PdfColors.black, width: 1.5)), ), children: [ pw.Text("SL NO", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("Item Code", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("Description", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("UNIT", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("QTY", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("Rate", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("Total Amt", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("VAT Amt", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), pw.Text("Net Amt", style: pw.TextStyle(font: font,fontSize: 7), textAlign: pw.TextAlign.center), ], ), // 数据行 ...itemData.map((item) => pw.TableRow( children: item.map((text) => pw.Text(text, style: const pw.TextStyle(fontSize: 10))).toList(), )), // 填充行:占满剩余空间 pw.TableRow( children: List.generate(9, (_) => pw.Expanded(child: pw.Text(""))), ), ], ), ); }
注意事项:
- 页面高度、行高参数需要根据实际纸张尺寸(如A4、Letter)和字体大小调整。
- 若需要精确计算行高,可使用
pw.TextPainter测量文本的实际高度。 - 数据行数超过页面可容纳行数时,表格仍会自动分页,不影响原有分页逻辑。
内容的提问来源于stack exchange,提问作者Fajar C P
相关产品推荐
相关产品推荐

