1

How do I print my whole multi-page UITableView (I need to scroll) and not just the part of the view which is currently displayed on screen?

4

1 回答 1

15

我假设您正在谈论使用 iOS 打印系统进行打印,如 iOS绘图和打印指南的“打印”一章中所述

由于-[UITableView viewPrintFormatter]不返回一个可用的UIViewPrintFormatter,你必须找到另一种方法来做到这一点。让我们编写一个将表格视图转换为 PDF 的函数:

static NSData *pdfDataWithTableView(UITableView *tableView) {

首先,我们将保存视图的当前边界,以便在最后恢复边界。

    CGRect priorBounds = tableView.bounds;

现在我们将要求 table view 计算出它需要多高才能容纳它的所有行。

    CGSize fittedSize = [tableView sizeThatFits:CGSizeMake(priorBounds.size.width, HUGE_VALF)];

我们将继续将表格视图调整为那么大。我们还将它的原点(与它的 相同contentOffset)设置为 0,0,因此它实际上将包含它的所有行。

    tableView.bounds = CGRectMake(0, 0, fittedSize.width, fittedSize.height);

我们需要一个CGRect包含 PDF 页面边界的文件。

    // Standard US Letter dimensions 8.5" x 11"
    CGRect pdfPageBounds = CGRectMake(0, 0, 612, 792);

现在我们可以创建一个 PDF 图形上下文。

    NSMutableData *pdfData = [[NSMutableData alloc] init];
    UIGraphicsBeginPDFContextToData(pdfData, pdfPageBounds, nil); {

我们需要将表格视图渲染到图形上下文中。由于表格视图可能高于页面大小,因此我们将上下文的原点沿 Y 轴以页面高度为增量进行步进。

        for (CGFloat pageOriginY = 0; pageOriginY < fittedSize.height; pageOriginY += pdfPageBounds.size.height) {

我们告诉上下文开始一个页面。

            UIGraphicsBeginPDFPageWithInfo(pdfPageBounds, nil);

由于我们要更改上下文的原点,我们将保存图形状态并在渲染此页面后恢复它。

            CGContextSaveGState(UIGraphicsGetCurrentContext()); {

现在我们可以调整上下文的原点,使渲染区域的左上角位于表格视图坐标系中的适当点。

                CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, -pageOriginY);

最后,我们可以告诉 table view 的 layer 将自己渲染到上下文中。当前页面范围之外的所有内容都将被剪掉。

                [tableView.layer renderInContext:UIGraphicsGetCurrentContext()];

为了清理,我们恢复图形状态。

            } CGContextRestoreGState(UIGraphicsGetCurrentContext());

此时,如果还有更多的页面,我们将回到for循环的顶部。

        }

现在我们已经渲染了所有页面,所以我们可以结束 PDF 图形上下文。

    } UIGraphicsEndPDFContext();

我们需要恢复表格视图的边界。

    tableView.bounds = priorBounds;

最后我们可以返回 PDF 数据。

    return pdfData;
}

这一切都在一起:

static NSData *pdfDataWithTableView(UITableView *tableView) {
    CGRect priorBounds = tableView.bounds;
    CGSize fittedSize = [tableView sizeThatFits:CGSizeMake(priorBounds.size.width, HUGE_VALF)];
    tableView.bounds = CGRectMake(0, 0, fittedSize.width, fittedSize.height);

    // Standard US Letter dimensions 8.5" x 11"
    CGRect pdfPageBounds = CGRectMake(0, 0, 612, 792);

    NSMutableData *pdfData = [[NSMutableData alloc] init];
    UIGraphicsBeginPDFContextToData(pdfData, pdfPageBounds, nil); {
        for (CGFloat pageOriginY = 0; pageOriginY < fittedSize.height; pageOriginY += pdfPageBounds.size.height) {
            UIGraphicsBeginPDFPageWithInfo(pdfPageBounds, nil);
            CGContextSaveGState(UIGraphicsGetCurrentContext()); {
                CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, -pageOriginY);
                [tableView.layer renderInContext:UIGraphicsGetCurrentContext()];
            } CGContextRestoreGState(UIGraphicsGetCurrentContext());
        }
    } UIGraphicsEndPDFContext();
    tableView.bounds = priorBounds;
    return pdfData;
}

你当然可以UIGraphicsBeginPDFContextToFile改用。那将使用更少的工作记忆。

无论哪种方式,一旦您拥有 PDF(在内存中或文件中),您就可以使用 iOS 打印系统将其发送到打印机。

于 2012-12-10T07:04:38.793 回答