Warum wird die untere Tabellenzelle mit zentriertem Text abgeschnitten, wenn sie als PDF in iOS angezeigt wird?

Lesezeit: 7 Minuten

Benutzer-Avatar
Zion Perez

Frage

Ich habe eine iOS-App, die eine HTML-Datei in ein PDF umwandelt und in einer WebKit-Webansicht anzeigt. Ich habe ein seltsames Problem, bei dem die untere Tabellenzelle abgeschnitten wird, wenn ich sie in PDF anzeige. Das Seltsame ist, dass die untere Tabelle nur dann abgeschnitten wird, wenn der Text zentriert ist. Wenn es linksbündig ist, funktioniert alles einwandfrei. Warum passiert das?

Bitte beachten Sie, dass ich nicht nach einer Umgehungslösung suche. Vielmehr versuche ich zu verstehen, warum dies geschieht. Ist das ein Bug in iOS? Oder habe ich etwas übersehen?

Überblick

In der Abbildung unten gibt es zwei Tabellen <table>. Eine Tabelle ist groß, hat einen rötlichen (korallenfarbenen) Hintergrund und eine Höhe von 505 Pixel. Die andere Tabelle befindet sich unter der ersten mit weißem Hintergrund (Höhe ist nicht festgelegt). Beide haben etwas Text. Der Text ist für beide Tabellen zentriert.

Der Titel der Navigationsleiste zeigt die Details der aktuellen Ansicht. Zum Beispiel, wie im Bild unten gezeigt, ein Titel von PDF Querformat 505 bedeutet, dass die Ansicht ein PDF im Querformat mit einer Haupttabellenhöhe von 505px anzeigt.

Geben Sie hier die Bildbeschreibung ein

Das Problem

Das Problem tritt auf, wenn ich die Höhe um 10 Pixel erhöhe. In der Abbildung unten beträgt die Höhe der Haupttabelle 515 Pixel und die untere Tabelle ist jetzt abgeschnitten.

Geben Sie hier die Bildbeschreibung ein

Nehmen Sie genau denselben HTML- und CSS-Code und ändern Sie nur die Textausrichtung auf linksbündig. Jetzt wird der untere Tisch nicht mehr abgeschnitten. Ich habe auch die Hintergrundfarbe zur Unterscheidung in Grün geändert. Grün bedeutet, dass Text linksbündig ist. Rot bedeutet, dass der Text zentriert ist.

Geben Sie hier die Bildbeschreibung ein

Das folgende Bild zeigt eine Haupttabellenhöhe von 745px und dennoch wird die untere Tabelle nicht abgeschnitten, da sie linksbündig ist.

Geben Sie hier die Bildbeschreibung ein

Code

Nachfolgend finden Sie den für diesen Test verwendeten HTML-Code.

<!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>

Im MyViewControllerdas getHTML() Funktion zieht die HTML-Quelle aus sample.html. Die Funktion ersetzt dann #ALIGN#, #COLOR#und #HEIGHT# mit ihren jeweiligen Werten.

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
}

Die PDFBuilder-Klasse behandelt die PDF-Erstellung mit einer Funktion:

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
} 

Dieses Projekt ist auch auf Github:
https://github.com/starkindustries/PrintPDFTest

Schritte zur Fehlerbehebung unternommen

  1. Abmessungen: Ich habe versucht, mit der Größe der PDF-Abmessungen herumzuspielen. Am Ergebnis änderte dies nichts.
  2. Spalten: Ich habe versucht, mehrere Spalten statt nur einer zu verwenden. Gleiches Problem; kein Unterschied.
  3. Tabellen: Ich habe versucht, nur eine Tabelle statt zwei zu verwenden. Bei einer Tabelle und zwei Zellen wird die unterste Zelle immer noch abgeschnitten, wenn der Text zentriert ist; Die unterste Zelle wird nicht abgeschnitten, wenn der Text linksbündig ausgerichtet ist.
  4. iPhones: Ich habe versucht, auf verschiedenen iPhone-Geräten (iPhone 6s, iPhone 8, iPad Pro) zu simulieren. Gleicher Fehler.
  5. Div: Wenn Sie statt einer zweiten Tabelle ein Div verwenden, wird das Problem auf magische Weise behoben. Aber warum funktioniert ein div und keine Tabelle?

App-Notizen

Die obere Symbolleiste hat zwei Schaltflächen: grün und rot. Grün macht den Text linksbündig. Rot macht den Text zentriert.

Geben Sie hier die Bildbeschreibung ein

Die untere Symbolleiste hat fünf Schaltflächen: zurückspulen, html, Porträt, Landschaftund schnell vorwärts. Das zurückspulen Schaltfläche reduziert die Höhe der Haupttabelle um 10 Pixel. Schneller Vorlauf erhöht die Höhe um 10px. Das html Schaltfläche zeigt die HTML-Ansicht. Porträt und Landschaft PDFs in ihrer jeweiligen Ausrichtung anzeigen.

Geben Sie hier die Bildbeschreibung ein

  • Gibt es anderes HTML oder CSS, das für die Frage wichtig sein könnte? Hier ist eine Geige jsfiddle.net/sol_b/6udog328

    – Sol

    8. Dezember 2017 um 15:58 Uhr

  • Nein, es gibt keinen anderen HTML/CSS-Code außer dem, den ich gepostet habe. Die vollständige Quelle finden Sie im Github-Link, wenn Sie sie überprüfen oder basteln möchten. Das Problem tritt in der iOS-App speziell beim Drucken in PDF auf. Es gibt kein Problem, wenn es als HTML angezeigt wird. Daher repliziert jsfiddle die Bedingungen nicht.

    – Zion Perez

    8. Dezember 2017 um 20:35 Uhr

  • Haben Sie versucht, eine explizite Höhe in Ihrer unteren Tabelle festzulegen?

    – Ken Boreham

    8. Dezember 2017 um 23:58 Uhr

  • Das sieht mir nach einem Bug aus. Wenn niemand etwas herausfindet, bevor das Kopfgeld abläuft, würde ich es melden hier.

    – Coder-256

    10. Dezember 2017 um 22:52 Uhr

  • @DeadLock, netter Vorschlag, es weiter einzugrenzen, aber kein Glück. Ich habe versucht, die Ausrichtung von zu entfernen table,th, td und verwendet td { text-align: #ALIGN#; }. Dasselbe Problem tritt auf.

    – Zion Perez

    15. Dezember 2017 um 11:23 Uhr

Ich hatte viele Probleme mit der PDF-Wiedergabe, um genau das gleiche Aussehen und die gleiche Größe wie meine einmal umgewandelte HTML-Datei beizubehalten (hauptsächlich wegen Auflösungsübersetzungsproblemen).

Die beste und einfachste Problemumgehung, die ich gefunden habe, besteht darin, den Inhalt in einem Container zu kapseln, der genau der Höhe des Dokuments entspricht. Sie können die Medienabfrage verwenden, um Ihren CSS-Code nur auf das Druckergebnis anzuwenden, wenn Sie Ihre Quell-HTML-Datei anzeigen möchten.

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>

  • Beachten Sie, dass die effizienteste Methode zum Korrigieren der Größe in einem PDF die Verwendung von „cm“ anstelle von „px“ ist, wenn Ihr Rendering-Tool dies zulässt, um eine Interpolation zu vermeiden

    – Fuchslabor

    9. Oktober 2019 um 8:40 Uhr

Ich verstehe, dass es irgendwann her ist, seit die Frage gepostet wurde. Aber ich war fasziniert davon und versuchte herauszufinden, warum dies passieren könnte.

Ich habe auch versucht, eine Vielzahl von Kombinationen zu testen, um dies zu überprüfen. Aber es sieht so aus, als könnte kein nativer iOS-Code hilfreich sein. Aber das Zuweisen einer Auto Höhe zum unterste Tabelle schien den Job zu machen. Das Setzen einer expliziten Höhe hat jedoch nicht funktioniert.

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

Es sieht so aus, als hätte das gerenderte PDF im anderen Fall ein Problem beim Einrichten des Rahmens für das PDF gehabt. Ich gehe davon aus, dass Sie auch wissen, dass das Problem sowohl im Hoch- als auch im Querformat bestand, wenn die Höhe eine bestimmte Grenze überschritten hat.

1187450cookie-checkWarum wird die untere Tabellenzelle mit zentriertem Text abgeschnitten, wenn sie als PDF in iOS angezeigt wird?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy