该页面可以包含自动翻译的文本。

如何布局 PDF 页面

PdfDocumentBuilder.Generate 方法向其委托提供一个 Document 类型的对象。使用该对象的 Pages 方法构建文档页面。你必须向该方法提供一个接受 PageLayout 类型参数的委托。

PDF 页面布局

如果 PDF 文档中的所有页面具有相同布局,一次调用该方法就足够了。如果文档中存在不同布局,请多次调用 Pages 方法。例如,你可以先调用该方法来布局封面页,然后再次调用该方法来描述报告正文。

每次调用 Pages 都会创建至少一页。如果没有为其提供内容,创建的页面可以为空。

本文是关于用于 PDF 生成的 Layout API 系列文章之一。如果你是首次使用该 API,请先阅读 Layout API 入门 部分。

内容槽

要描述页面布局,请使用预定义容器。我也将它们称为内容槽。你可以通过调用 PageLayout 对象的方法访问这些容器。

有三个主要槽:ContentHeaderFooter。另外还有两个用于附加内容的槽:BackgroundForeground。默认情况下,这五个容器都是空的,不占用任何页面空间。你可以根据需求在这些槽之间分配页面内容。

阅读 容器及其内容 文章,了解如何使用容器布局页面。

你不会感到意外,页眉和页脚内容分别进入 HeaderFooter 槽。该 API 会在每个生成的页面上方和下方重复这些槽。Layout API 从不在页面之间拆分页眉或页脚内容。如果页眉或页脚无法适配到页面上,你将获得 LayoutException

主内容

页面的主要内容,如图像、表格和文本,进入 Content 槽。Layout API 会自动将这些内容拆分页。

以下代码将简单文本内容分配到所有主要内容槽。代码还为这些槽设置了背景色。

PdfDocumentBuilder.Create().Generate("pages-main-slots.pdf", doc => doc.Pages(pages => {
    pages.Header()
        .Text("This text goes to the header")
        .BackgroundColor(new PdfRgbColor(66, 135, 245));

    pages.Content()
        .Text("The main content goes in this slot")
        .BackgroundColor(new PdfRgbColor(242, 233, 206));

    pages.Footer()
        .Text("This is the footer contents")
        .BackgroundColor(new PdfRgbColor(194, 192, 188));
}));

请查看代码在 pages-main-slots.pdf 中的结果。

如你所见,每个槽只占据页面的一部分。精确区域取决于槽内内容。Header 槽贴在页面顶部。Content 槽紧接在 Header 之后开始。Footer 槽贴在底部。

附加内容

BackgroundForeground 提供可用于水印、覆盖层和背景的容器。Background 槽中的所有内容都位于页面的页眉、页脚和主体内容之下。Foreground 槽中的内容会覆盖页面上添加的所有内容。

这些容器占据整页。这是这些容器的独特特性。API 会在每个生成的页面上重复其内容,页眉和页脚容器也是如此。

我在上面的代码中添加了几行,展示如何使用 ForegroundBackground 容器。

PdfDocumentBuilder.Create().Generate("pages-all-slots.pdf", doc => doc.Pages(pages => {
    // ... 

    pages.Background()
        .Background(new PdfRgbColor(208, 227, 204));

    pages.Foreground()
        .Rotate(45)
        .Text(new string(' ', 30) + "Your watermark could go here, in the foreground");
}));

对于 Background 容器,我不提供任何文本或其他内容,只指定背景色。页眉、主体内容和页脚下方的所有内容都会显示这种绿色。

我旋转 Foreground 容器中的内容,并添加一些文本。由于前导空格,文本不会覆盖页眉或页脚内容。所有容器中的内容都会显示在页面上。

你可以在 pages-all-slots.pdf 中查看代码结果。

设置

到目前为止,所有代码片段都聚焦于构成页面的容器。现在该看看如何自定义页面本身,而不是其内容槽了。

要设置页面,请使用 PageLayout 类的方法。请记住,PageLayout 对象可以描述多于一页。方法调用会影响你描述的所有页面。

尺寸

最基本的设置大概是页面尺寸。你可以使用 Size 方法为页面指定一种预定义尺寸。这里包含所有常见尺寸,如 A4、Ledger 或 Monarch Envelope。

你也可以选择为页面指定方向。还可以通过以磅为单位提供宽度和高度来设置自定义页面尺寸。

页边距

页面页边距有助于提高可读性、美观性和整体版式。

使用 Margin 方法将所有页边距设置为相同的磅值。使用 MarginVerticalMarginHorizontal 方法只设置垂直或水平页边距。使用 MarginLeft/Top/Right/Bottom 方法可分别指定每个页边距。

文本样式

Layout API 提供 TextStyle 类用于创建文本样式。你可以创建并将样式应用到文本上,以获得所需外观。

有些情况下,页面上的大段文本会使用相同样式。你可以将该样式设置为页面的默认文本样式。默认样式会影响主要内容槽中的所有文本。但你可以为某些元素覆盖默认样式。只需将另一种样式应用到需要不同外观的文本片段即可。

PdfDocumentBuilder.Create().Generate("pages-text-styles.pdf", doc =>
{
    var defaultStyle = TextStyle.Parent.FontSize(30);
    var tightSpacing = TextStyle.Parent.LetterSpacing(-0.1);

    doc.Pages(pages =>
    {
        pages.TextStyle(defaultStyle);

        pages.Content().Text(t =>
        {
            t.Line("This line uses the default text style.");
            t.Line("This line uses a tight letter spacing.").Style(tightSpacing);
            t.Line("This line uses the default text style, again.");
        });
    });
});

你可以在 pages-text-styles.pdf 中查看代码结果。

请注意,你可以使用 Document.Typography 方法设置整个文档范围的文本样式。Typography 类中的每个属性都为某种使用场景定义一种样式。这些样式会覆盖 PageLayout.TextStyle 方法指定的样式。例如,Typography.Body 属性会覆盖 Content 容器中文本的默认样式。

内容方向

有些语言从右到左书写。Layout API 可以正常处理这些语言的文本。但你需要显式指定文本方向。

如果页面上的大部分文本使用 RTL 语言,你可以将从右到左设置为页面的默认内容方向。这样你就可以为页面中的任意容器指定不同方向。

PdfDocumentBuilder.Create().Generate("pages-content-direction.pdf", doc =>
{
    var defaultTextStyle = doc.TextStyleWithFont(SystemFont.Family("Calibri"));

    doc.Pages(pages =>
    {
        pages.Size(PdfPaperSize.A6).TextStyle(defaultTextStyle);

        pages.ContentFromRightToLeft();

        pages.Content().Column(column =>
        {
            column.Item()
                .ContentFromLeftToRight()
                .Text("There are languages written from right to left.");

            column.Item()
                .Text("هناك لغات تكتب من اليمين إلى اليسار.");

            column.Item()
                .Text("יש שפות שנכתבות מימין לשמאל.");
        });
    });
});

在上面的代码中,我将从右到左设置为默认内容方向。对于包含英文短语的容器,我将方向改为从左到右。你可以在 pages-content-direction.pdf 中查看代码结果。

页码

在生成 PDF 时,Layout API 会自动计算当前页码。它还会计算文档中的总页数。你可以通过调用任意文本容器的 CurrentPageNumberPageCount 方法获取这些数字。无论容器位于页眉、页脚还是主体内容槽中都一样。

PdfDocumentBuilder.Create().Generate("pages-page-numbers.pdf", doc => doc.Pages(pages =>
{
    pages.Content().Text(t =>
    {
        t.Span("This line is on page ");
        t.CurrentPageNumber();
        t.Line();
        t.Line("Check the footer.");
    });

    pages.Footer().Row(r =>
    {
        r.AutoItem().Text("Created with Docotic.Pdf Layout API");

        r.RelativeItem(2).Text(t =>
        {
            t.AlignRight();

            t.Span("Page ");
            t.CurrentPageNumber();
            t.Span(" of ");
            t.PageCount();
        });
    });
}));

代码结果位于 pages-page-numbers.pdf

这两个方法都会返回一个 TextPageNumber 实例,你可以用它来格式化数字。

向 PDF 文档添加页眉和页脚 示例展示如何为页码应用自定义格式。

示例代码

我们有一些示例应用更详细地涵盖了上述功能。请花些时间查看它们。