【发布时间】:2020-06-20 07:08:52
【问题描述】:
根据this caseAlexey 的回答,我们可以利用不同的渲染器和自定义的 RootLayoutArea 来实现如下布局行为。
代码如下:
public void ManipulatePdf(String dest)
{
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc, PageSize.A4);
doc.SetMargins(36, 36, 36, 36);
Paragraph p = new Paragraph();
p.SetBorder(new SolidBorder(0.5f));
for (int i = 1; i <= 500; i++)
{
p.Add(new Text(i + " "));
}
doc.Add(p);
RootLayoutArea endOfFullWidthContentArea = (RootLayoutArea)doc.GetRenderer().GetCurrentArea();
ExtendedDocumentRenderer renderer1 = new ExtendedDocumentRenderer(doc,
new RootLayoutArea(endOfFullWidthContentArea.GetPageNumber(), endOfFullWidthContentArea.GetBBox().Clone().SetWidth(200)));
doc.SetRightMargin(doc.GetRightMargin() + doc.GetPageEffectiveArea(PageSize.A4).GetWidth() - 200);
doc.SetRenderer(renderer1);
//The paragraph drawn in the left
Paragraph p1 = new Paragraph();
p1.SetBorder(new SolidBorder(0.5f));
for (int i = 1; i <= 500; i++)
{
p1.Add(new Text(i + " "));
}
doc.Add(p1);
ExtendedDocumentRenderer renderer2 = new ExtendedDocumentRenderer(doc,
new RootLayoutArea(endOfFullWidthContentArea.GetPageNumber(),
endOfFullWidthContentArea.GetBBox().Clone().MoveRight(200 + 20)
.SetWidth(endOfFullWidthContentArea.GetBBox().GetWidth() - 200 - 20)));
doc.SetRightMargin(36);
doc.SetLeftMargin(200 + 36 + 20);
doc.SetRenderer(renderer2);
Paragraph p2 = new Paragraph();
for (int i = 1; i <= 1000; i++)
{
p2.Add(new Text(i + " "));
}
doc.Add(p2);
//Compute which free area is lower in the document
RootLayoutArea areaColumn1 = (RootLayoutArea)renderer1.GetCurrentArea();
RootLayoutArea areaColumn2 = (RootLayoutArea)renderer2.GetCurrentArea();
RootLayoutArea downArea =
areaColumn1.GetPageNumber() > areaColumn2.GetPageNumber() ? areaColumn1 :
(areaColumn1.GetPageNumber() < areaColumn2.GetPageNumber() ? areaColumn2 :
(areaColumn1.GetBBox().GetTop() < areaColumn2.GetBBox().GetTop() ? areaColumn1 : areaColumn2));
doc.SetMargins(36, 36, 36, 36);
DocumentRenderer renderer3 = new ExtendedDocumentRenderer(doc,
new RootLayoutArea(downArea.GetPageNumber(), downArea.GetBBox().Clone().SetX(36).SetWidth(doc.GetPageEffectiveArea(PageSize.A4).GetWidth())));
doc.SetRenderer(renderer3);
Paragraph p3 = new Paragraph();
for (int i = 1; i <= 1000; i++)
{
p3.Add(new Text(i + " "));
}
doc.Add(p3);
doc.Close();
}
private class ExtendedDocumentRenderer : DocumentRenderer
{
public ExtendedDocumentRenderer(Document document, RootLayoutArea currentArea) : base(document)
{
this.currentArea = new RootLayoutArea(currentArea.GetPageNumber(), currentArea.GetBBox().Clone());
this.currentPageNumber = this.currentArea.GetPageNumber();
}
}
我们可以看到左栏的第1段跨越两页,第2段跨越三页,在这种情况下代码运行良好。
但如果我们在第 1 段中添加更多内容,使其跨越 3 页,如下所示:
//The paragraph drawn in the left has more contents
Paragraph p1 = new Paragraph();
p1.SetBorder(new SolidBorder(0.5f));
for (int i = 1; i <= 800; i++)
{
p1.Add(new Text(i + " "));
}
doc.Add(p1);
在第 2 段渲染时,它会抛出“无法在已刷新的页面上绘制元素”的异常。如何解决这个问题呢?谢谢!
【问题讨论】: