使用iText PDF 7无法居中页脚?样式被覆盖问题求助
问题描述
我正在开发一款PDF生成器,需根据生成的文件类型添加两种不同页脚:一种是仅显示“This PDF is a sample”文本的页脚,另一种是包含短描述和两个Logo的三列表格页脚。但调用事件处理器后,文本和表格的样式均被覆盖,无法将页脚居中;表格还出现宽度被压缩、Logo与文本无间距的问题,且页脚位置会随页数变化。我已尝试为所有对象设置水平对齐,相关代码如下:
单元格代码
Image trustedImage = new Image(ImageDataFactory.create(pathLogo3)); trustedImage.scaleToFit(100, 100); Cell trustedIdentity = new Cell().setBorder(new SolidBorder(whiteColor, 1f)); trustedIdentity.add(trustedImage.setHorizontalAlignment(HorizontalAlignment.CENTER)); table.addCell(trustedIdentity.setVerticalAlignment(VerticalAlignment.MIDDLE));
事件处理器调用代码
pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new TableFooterEventHandler(creaTabellaFineDocumentoPlaceholder()));
TableFooterEventHandler类代码
import com.itextpdf.kernel.events.Event; import com.itextpdf.kernel.events.IEventHandler; import com.itextpdf.kernel.events.PdfDocumentEvent; import com.itextpdf.kernel.geom.Rectangle; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfPage; import com.itextpdf.kernel.pdf.canvas.PdfCanvas; import com.itextpdf.layout.Canvas; import com.itextpdf.layout.element.Table; import com.itextpdf.layout.properties.HorizontalAlignment; public class TableFooterEventHandler implements IEventHandler { private Table table; public TableFooterEventHandler(Table table) { this.table=table; } @Override public void handleEvent(Event event) { PdfDocumentEvent docEvent = (PdfDocumentEvent) event; PdfDocument pdfDoc = docEvent.getDocument(); PdfPage page = docEvent.getPage(); PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc); float tableHeight = table.getHeight() == null ? 30 : table.getHeight().getValue(); float tableWidth = table.getWidth() == null ? 30 : table.getWidth().getValue(); float x = (page.getPageSize().getWidth() - table.getWidth().getValue()) /2; new Canvas(canvas, new Rectangle(x, 20, table.getWidth().getValue(), 30)) .add(table.setHorizontalAlignment(HorizontalAlignment.CENTER)).setHorizontalAlignment(HorizontalAlignment.CENTER) .close(); } }
我遵循iText官方示例开发,但除页脚样式外其他功能勉强可用,求问问题原因及修复方法。
问题分析与修复方案
1. 页脚无法居中、宽度压缩问题
原因
- 复用同一个
Table实例,iText添加到Canvas后会修改其内部状态,后续页面复用会导致样式错乱; - 未显式设置表格宽度,表格会自动收缩为内容宽度,引发压缩;
- Canvas高度硬编码为30,若表格实际高度超出,会挤压内容。
修复代码
修改事件处理器,每次处理事件时创建表格副本,显式设置表格宽度为页面可用宽度:
import com.itextpdf.kernel.events.Event; import com.itextpdf.kernel.events.IEventHandler; import com.itextpdf.kernel.events.PdfDocumentEvent; import com.itextpdf.kernel.geom.Rectangle; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfPage; import com.itextpdf.kernel.pdf.canvas.PdfCanvas; import com.itextpdf.layout.Canvas; import com.itextpdf.layout.element.Table; import com.itextpdf.layout.properties.HorizontalAlignment; import com.itextpdf.layout.properties.UnitValue; public class TableFooterEventHandler implements IEventHandler { private final Table templateTable; public TableFooterEventHandler(Table templateTable) { this.templateTable = templateTable; } @Override public void handleEvent(Event event) { PdfDocumentEvent docEvent = (PdfDocumentEvent) event; PdfDocument pdfDoc = docEvent.getDocument(); PdfPage page = docEvent.getPage(); PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc); Rectangle pageSize = page.getPageSize(); float footerWidth = pageSize.getWidth() - 40; // 左右各留20边距 // 创建表格副本,避免状态污染 Table table = new Table(templateTable.getNumberOfColumns()) .setWidth(UnitValue.createPercentValue(100)) .setHorizontalAlignment(HorizontalAlignment.CENTER); // 复制原表格的单元格内容 for (int i = 0; i < templateTable.getNumberOfRows(); i++) { table.addCell(templateTable.getCell(i).clone(true)); } float footerY = 20; // 固定页脚在底部20位置 float tableHeight = table.getHeight() != null ? table.getHeight().getValue() : 50; new Canvas(canvas, new Rectangle(pageSize.getLeft() + 20, footerY, footerWidth, tableHeight)) .add(table) .close(); } }
2. Logo与文本无间距问题
原因
单元格未设置内边距,导致图片紧贴边框。
修复代码
修改单元格创建逻辑,添加内边距:
Image trustedImage = new Image(ImageDataFactory.create(pathLogo3)); trustedImage.scaleToFit(100, 100); Cell trustedIdentity = new Cell() .setBorder(new SolidBorder(whiteColor, 1f)) .setPadding(10) // 添加内边距拉开间距 .setVerticalAlignment(VerticalAlignment.MIDDLE); trustedIdentity.add(trustedImage.setHorizontalAlignment(HorizontalAlignment.CENTER)); table.addCell(trustedIdentity);
3. 页脚位置随页数变化问题
原因
原代码Canvas高度硬编码为30,表格高度超出时会导致内容溢出,位置偏移。修复后通过固定Y坐标,同时根据表格实际高度设置Canvas高度,确保页脚位置稳定。
4. 纯文本页脚居中问题
针对文本页脚,创建独立事件处理器,确保每次使用新的文本实例并设置居中:
import com.itextpdf.kernel.events.Event; import com.itextpdf.kernel.events.IEventHandler; import com.itextpdf.kernel.events.PdfDocumentEvent; import com.itextpdf.kernel.geom.Rectangle; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfPage; import com.itextpdf.kernel.pdf.canvas.PdfCanvas; import com.itextpdf.layout.Canvas; import com.itextpdf.layout.element.Paragraph; import com.itextpdf.layout.properties.HorizontalAlignment; public class TextFooterEventHandler implements IEventHandler { @Override public void handleEvent(Event event) { PdfDocumentEvent docEvent = (PdfDocumentEvent) event; PdfDocument pdfDoc = docEvent.getDocument(); PdfPage page = docEvent.getPage(); PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc); Rectangle pageSize = page.getPageSize(); Paragraph footerText = new Paragraph("This PDF is a sample") .setHorizontalAlignment(HorizontalAlignment.CENTER) .setFontSize(10); float footerY = 20; new Canvas(canvas, new Rectangle(pageSize.getLeft(), footerY, pageSize.getWidth(), 20)) .add(footerText) .close(); } }
内容的提问来源于stack exchange,提问作者asdrubalo
相关产品推荐
相关产品推荐

