为啥在 iOS 中显示为 PDF 时,具有居中文本的底部表格单元格会被截断?

Posted

技术标签:

【中文标题】为啥在 iOS 中显示为 PDF 时,具有居中文本的底部表格单元格会被截断?【英文标题】:Why does bottom table cell that has centered-text get cut off when displayed as PDF in iOS?为什么在 iOS 中显示为 PDF 时,具有居中文本的底部表格单元格会被截断? 【发布时间】:2018-05-19 04:46:39 【问题描述】:

问题

我有一个 ios 应用程序,它获取一个 html 文件,将其转换为 PDF,并将其显示到 WebKit 网络视图。我有一个奇怪的问题,当我显示为 PDF 时,底部表格单元格被截断。奇怪的是,底部表格仅在文本居中时才被切断。如果它是左对齐的,一切正常。为什么会这样?

请注意,我不是在寻找解决方案。相反,我试图理解为什么会发生这种情况。这是iOS中的错误吗?还是我错过了什么?

概述

在下图中,有两个表<table>。一张桌子很大,背景为红色(珊瑚色),高度为 505 像素。另一个表格位于第一个表格下方,背景为白色(未设置高度)。两者都有一些文字。两个表格的文本都居中。

导航栏标题显示当前视图的详细信息。例如,如下图所示,标题为 PDF Landscape 505 表示视图以横向尺寸显示 PDF,主表格高度为 505px。

问题

当我将高度增加 10 像素时出现问题。在下图中,主表高度为 515px,下面的表现在被截断了。

采用完全相同的 html 和 css 代码,仅将文本对齐更改为左对齐。现在下桌不再被切断。我还将背景颜色更改为绿色以进行区分。绿色表示文本左对齐。红色表示文本居中。

下图显示了一个高度为 745px 的主表,而下面的表仍然没有被截断,因为它是左对齐的。

代码

以下是用于此测试的 html 代码。

<!DOCTYPE html>
<html>
<head>
  <title>#COLOR#</title>
  <meta charset="utf-8">
  <style>
  table, th, td 
    border-collapse: collapse;
    border: 3px solid black;
    text-align: #ALIGN#;
  
  table.main-table 
    width: 1012px;
    height: #HEIGHT#px;
    background-color: #COLOR#;
  
  table.bottom-table 
    width: 1012px;
  
  </style>
</head>

<body>

  <table class="main-table">
    <tr><td>Hello World.</td></tr>
  </table>
  <table class="bottom-table">
    <tr><td>This text gets cut off when centered. It does *not* get cut when left-aligned.</td></tr>
  </table>

</body>
</html>

MyViewController 中,getHTML() 函数从sample.html 拉取html 源代码。然后该函数将#ALIGN##COLOR##HEIGHT# 替换为它们各自的值。

func getHTML() -> String? 
    let htmlPath: String? = Bundle.main.path(forResource: htmlResource, ofType: "html")
    guard let path = htmlPath else  return nil 
    do 
        // Load the HTML template code into a String variable.
        var html = try String(contentsOfFile: path)
        html = html.replacingOccurrences(of: "#HEIGHT#", with: tableHeight.description)
        html = html.replacingOccurrences(of: "#COLOR#", with: colorState.rawValue)
        html = html.replacingOccurrences(of: "#ALIGN#", with: alignState.rawValue)
        return html
     catch 
        print("Error: " + error.localizedDescription)
    
    return nil

PDFBuilder 类使用一个函数处理 PDF 创建:

static func exportHTMLToPDF(html: String, frame: CGRect) -> Data 
    // Set a printable frame and inset                
    let pageFrame = frame
    let insetRect = pageFrame.insetBy(dx: 10.0, dy: 10.0)

    // Create a UIPrintPageRenderer and set the paperRect and printableRect using above values.
    let pageRenderer = UIPrintPageRenderer()
    pageRenderer.setValue(pageFrame, forKey: "paperRect")
    pageRenderer.setValue(insetRect, forKey: "printableRect")

    // Create a printFormatter and pass the HTML code as a string.
    let printFormatter = UIMarkupTextPrintFormatter(markupText: html)

    // Add the printFormatter to the pageRenderer
    pageRenderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)

    // This data var is where the PDF will be stored once created.
    let data = NSMutableData()

    // This is where the PDF gets drawn.
    UIGraphicsBeginPDFContextToData(data, pageFrame, nil)
    UIGraphicsBeginPDFPage()
    pageRenderer.drawPage(at: 0, in: UIGraphicsGetPDFContextBounds())
    print("bounds: " + UIGraphicsGetPDFContextBounds().debugDescription)        
    UIGraphicsEndPDFContext()

    return data as Data
 

这个项目也在 Github 上: https://github.com/starkindustries/PrintPDFTest

已采取的故障排除步骤

    尺寸:我尝试调整 PDF 尺寸的大小。这对结果没有影响。 列:我尝试使用多列而不是只使用一列。同样的问题;没有区别。 表格:我尝试只使用一张而不是两张。一个表格和两个单元格,文本居中时底部单元格仍然被截断;文本左对齐时,底部单元格不会被剪切。 iPhones:我尝试在不同的 iPhone 设备(iPhone 6s、iPhone 8、iPad Pro)上进行模拟。同样的问题。 Div:如果您使用 div 而不是第二个表,问题就会神奇地得到解决。但是为什么一个 div 工作而不是一个表呢?

应用笔记

顶部工具栏有两个按钮:greenred。绿色使文本左对齐。红色使文本居中。

底部工具栏有五个按钮:rewindhtmlportraitlandscape快进rewind 按钮将主表格的高度降低 10 像素。 快进将高度增加 10 像素。 html 按钮显示 html 视图。 纵向横向以各自的方向显示 PDF。

【问题讨论】:

还有其他可能对这个问题很重要的 HTML 或 CSS 吗?这是一个小提琴jsfiddle.net/sol_b/6udog328 不,除了我发布的内容之外,没有其他 HTML/CSS 代码。如果您想验证或修改,完整的源代码在 github 链接中。该问题出现在 iOS 应用程序中,特别是在打印到 PDF 时。当它显示为html时没有问题。因此,jsfiddle 不会复制条件。 您是否尝试在底部表格中设置明确的高度? 这对我来说似乎是一个错误。如果在赏金到期之前没有人弄清楚任何事情,那么我会报告它here @DeadLock,很好的建议进一步缩小范围,但没有运气。我尝试从table,th, td 中删除对齐并使用td text-align: #ALIGN#; 。出现同样的问题。 【参考方案1】:

我知道问题发布已经有一段时间了。但我对此很感兴趣,并试图弄清楚为什么会发生这种情况。

我还尝试测试各种组合来验证这一点。但似乎没有原生 iOS 代码可以提供任何帮助。但是,将 auto 高度分配给 bottom-table 似乎可以完成这项工作。但是设置显式高度不起作用。

table.bottom-table 
    width: 1012px;
    height: auto;

在另一种情况下,看起来正在呈现的 PDF 可能在设置 PDF 的框架时遇到了一些问题。我假设您也知道在纵向和横向模式下,当高度超过某个限制时,该问题仍然存在。

【讨论】:

【参考方案2】:

我在 PDF 渲染方面遇到了很多麻烦,以便在我的 HTML 文件转换后保持完全相同的纵横比和大小(主要是因为分辨率转换问题)。

我发现最好和最简单的解决方法是将内容封装在一个完全适合文档高度的容器中。 如果要显示源 html 文件,可以使用媒体查询仅在打印结果上应用 css 代码。

table, th, td 
  border-collapse: collapse;
  border: 3px solid black;
  text-align: center;


table.main-table 
  width: 1012px;
  height: 515px;
  background-color: #f4f4f4;


table.bottom-table 
  width: 1012px;


@media print 
  .main-container
    height:1100px;/* adjust the height to fit your PDF document*/
  
<div class="main-container">
  <table class="main-table">
    <tr><td>Hello World.</td></tr>
  </table>
  <table class="bottom-table">
    <tr><td>This text gets cut off when centered. It does *not* get cut when left-aligned.</td></tr>
  </table>
 </div>

【讨论】:

请注意,如果您的渲染工具允许,在 PDF 中固定大小的最有效方法是使用“cm”而不是“px”,以避免插值

以上是关于为啥在 iOS 中显示为 PDF 时,具有居中文本的底部表格单元格会被截断?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PDFBox 使文本居中

iOS 无法选择/突出显示 PDF 中的文本

iOS - 我们将弹出的菜单类型称为啥,如突出显示文本时所见

iOS 中 PDF Reader 和 Writer 中的文本格式

Rmarkdown 文本突出显示未显示在 PDF 输出中

在 iOS 上将图像和文本内联居中