該頁面可以包含自動翻譯的文字。

容器及其內容

文件是由一組頁面構成的。每個頁面又是由一組內容片段構成的。您可能已經知道,PageLayout 類別會為主要與附加內容提供容器。但這些容器該怎麼使用呢?

頁面內容的容器

容器有助於組織頁面上的內容。您放到頁面上的所有內容都必須放入容器中。如果內容足夠大,容器可以跨越多個頁面佔用空間。

您可以將一些文字或圖片放入容器中。為了對齊與定位,您可以將一個容器放入另一個容器中。也有一些容器可容納超過一個內容片段。

頁面上的容器由 LayoutContainer 類別的物件表示。使用此類別來設定容器的大小、位置、內容與渲染流程。

本文是關於用於 PDF 產生的 Layout API 系列文章之一。如果您是 API 新手,請先閱讀 Layout API 入門 部分。

容器如何運作

首先取得一個容器。例如,呼叫 PageLayout.Content 方法。此方法會傳回一個不佔用空間且未設定任何內容或屬性的容器。使用 LayoutContainer 類別的方法來設定容器。

最重要的是理解:所有 LayoutContainer 方法都會將內容放入容器中。當您向容器新增一些文字時,這是預期行為。但當您設定縮排或寬度時,內容會變成什麼?

當您設定容器屬性時,程式庫會建立一個具有指定屬性的容器。新容器會成為原始容器的內容。程式庫會將巢狀容器作為方法結果傳回。

巢狀容器的屬性會影響父容器,反之亦然。例如,巢狀容器的寬度會影響父容器的大小。父容器的預設文字樣式會影響巢狀容器中的文字。Layout 附加元件會使用容器階層及其屬性來建立最終版面配置。

以下程式碼的結果 可能會讓您驚訝,但請花一些時間分析它。此程式碼說明巢狀容器的運作方式。

PdfDocumentBuilder.Create().Generate("containers-how.pdf", doc => doc.Pages(page =>
{
    page.Size(150, 150);
    page.Content()
        .Background(new PdfRgbColor(235, 64, 52)) // 紅色

        .PaddingTop(50)
        .Background(new PdfRgbColor(187, 237, 237)) // 藍色

        .PaddingRight(50)
        .Background(new PdfRgbColor(15, 130, 9)) // 綠色

        .PaddingBottom(50)
        .Background(new PdfRgbColor(250, 123, 5)) // 橘色

        .PaddingLeft(50)
        .Background(new PdfRgbColor(204, 204, 204)); // 灰色
}));

裝飾

文件設計不僅是排版文字與圖片。設計得當的文件不僅能有效傳達資訊,也更具視覺吸引力。

使用 Layout API,您可以為任何容器套用背景色彩。這有助於在內容中建立層次。您也可以透過套用邊框來定義邊界。使用垂直線與水平線來分隔內容元素。

PdfDocumentBuilder.Create().Generate("containers-decor.pdf", doc => doc.Pages(page =>
{
    page.Size(150, 150);
    page.Content()
        .Background(new PdfRgbColor(250, 123, 5))
        .Border(b =>
        {
            b.Color(new PdfGrayColor(0), 50);
            b.Thickness(15);
        })
        .PaddingTop(74)
        .LineHorizontal(2)
            .Color(new PdfCmykColor(73, 45, 0, 4))
            .DashPattern(new PdfDashPattern(new double[] { 8, 2 }));
}));

API 支援 GrayRGBCMYK 色彩空間中的不透明與半透明色彩。除了實線之外,Layout API 也支援使用 dash patterns 的線條。

上述程式碼的結果見 containers-decor.pdf

內容

讓我們看看 LayoutContainer 類別為組織內容提供了哪些功能。

Text

若要向容器新增文字,請使用 Text 方法之一。

如果所有文字都使用相同樣式,請使用該方法的簡寫版本。該版本接受字串並傳回 TextSpan 物件。您可以使用該物件來設定該區段的文字樣式。

Text 方法還有另一個版本,接受類型為 Action<TextContainer> 的委派。使用該版本可在同一段文字中包含不同樣式的區段。TextContainer 提供方法,可在文字區段之間插入圖片與其他元素。還有其他進階功能,例如設定段落間距。

PdfDocumentBuilder.Create().Generate("containers-text.pdf", doc => doc.Pages(page =>
{
    page.Header().Text("This is a simple text span");

    page.Content().Text(t =>
    {
        t.Span("This line contains ");
        t.Span("some underlined text").Style(TextStyle.Parent.Underline());
    });
}));

您可以在 containers-text.pdf 中查看程式碼結果。

Image

Layout API 提供方法,可從檔案或資料流中的圖片資料建立 Image 物件。任何 [Image] 物件都可以作為容器內容。您可以在多個容器中使用相同的 [Image] 物件。不同的內容模式會影響圖片在容器中的顯示方式。

程式庫只能載入點陣格式圖片:PNG、JPEG、JPEG 2000、BMP、GIF 和 TIFF。

PdfDocumentBuilder.Create().Generate("containers-image.pdf", doc =>
{
    var imageFile = new FileInfo(@"path-to-image.jpg");
    var image = doc.Image(imageFile);

    doc.Pages(pages =>
    {
        pages.Size(image.Width, image.Height);
        pages.Content().Image(image, ImageContentMode.FitArea);
    });
});

Column

欄可提供垂直依序排列無限數量項目的空間。您可以在欄內使用任何類型的項目。例如,欄可以包含圖片與文字項目。每個項目的寬度都等於欄寬。每個項目的高度取決於其內容與屬性。

PdfDocumentBuilder.Create().Generate("containers-column.pdf", doc => doc.Pages(page =>
{
    page.Content().Column(c =>
    {
        for (int i = 0; i < 10; i++)
        {
            PdfColor color = i % 2 == 0
                ? new PdfRgbColor(187, 237, 237)
                : new PdfGrayColor(66);

            c.Item().Background(color).Height(10 + i * 3);
        }
    });
}));

您可以在 containers-column.pdf 中查看程式碼結果。

關於 Column 容器功能的詳細資訊,請參閱 複合容器 文章。

Row

Row 容器有助於水平組織無限數量的項目。列中的每個項目都是一個容器。因此,您可以在列中放入不同類型的內容。

var rowItems = new[] { "three", "two", "one" };

PdfDocumentBuilder.Create().Generate("containers-row.pdf", doc => doc.Pages(page =>
{
    page.Content().Row(row =>
    {
        for (int index = 0; index < rowItems.Length; index++)
        {
            row.AutoItem().Text(rowItems[index]);

            if (index != rowItems.Length - 1)
                row.AutoItem().PaddingHorizontal(10).LineVertical(0.5);
        }
    });
}));

您可以在 containers-row.pdf 中查看程式碼結果。

複合容器 文章包含 Row 容器的詳細資訊。

Table

使用 Table 容器來排版最複雜的資料。先定義至少一個欄,然後透過多次呼叫 Cell 方法來填入欄與列。

表格可以有頁首與頁尾。表格中的儲存格可以跨越多個欄和/或列。以下程式碼會新增一個簡單表格。

PdfDocumentBuilder.Create().Generate("containers-table.pdf", doc => doc.Pages(page =>
{
    page.Content().Table(t =>
    {
        t.Columns(c =>
        {
            for (int i = 0; i < 4; ++i)
                c.ConstantColumn(50);
        });

        for (int i = 0; i < 16; i++)
        {
            t.Cell()
                .Border(b => b.Thickness(0.5))
                .PaddingHorizontal(10)
                .Text($"{i + 1}");
        }
    });
}));

程式碼的結果見 containers-table.pdf

所有 Table 容器功能的說明請參閱 表格容器 文章。

Inlined

InlineContainer 容器類型提供了一種方便方式,可使用容器集合中的項目填滿一個區域。您只要依序新增項目,程式庫就會將它們依序放在一列中。如果沒有足夠空間放置某個項目,程式庫就會開始新的一列。

關於 InlineContainer 容器的更多資訊,請參閱 複合容器 文章。

Layers

有些情況下,將內容放在多個圖層上會比較合適。LayerContainer 容器類型正是為此而設。您必須明確定義一個主要圖層,以及任意數量的非主要圖層。Layout API 會依照您建立圖層的順序進行合成。

關於 LayerContainer 類型的更多細節,請參閱 複合容器

Element

這是一種特殊的內容。您可以動態建立元素,並將結果放入容器中。

動態建立的元素可以提供依賴頁碼、大小及其他屬性的版面配置。