質問
Htmlファイルを取得してPDFに変換し、WebKitWebビューに表示するiOSアプリがあります。 PDFに表示すると、下のテーブルセルが途切れるという奇妙な問題があります。奇妙なことに、下のテーブルはテキストが中央に配置されている場合にのみ切り取られます。左揃えの場合、すべてが正常に機能します。なぜこれが起こるのですか?
私は回避策を探していないことに注意してください。むしろ、なぜこれが起こるのかを理解しようとしています。これはiOSのバグですか?それとも私は何かを逃しましたか?
概要
以下の画像には、2つのテーブル_<table>
_があります。 1つのテーブルは大きく、背景は赤みがかっており(珊瑚)、高さは505pxです。もう1つのテーブルは、最初のテーブルの下にあり、背景は白です(高さは設定されていません)。どちらにもテキストがあります。テキストは両方のテーブルの中央に配置されます。
ナビゲーションバーのタイトルには、現在のビューの詳細が表示されます。たとえば、次の画像に示すように、PDF Landscape 505というタイトルは、ビューにPDFメインテーブルの高さが505pxの横向きの寸法。
問題
高さを10px増やすと、問題が発生します。下の画像では、メインテーブルの高さは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クラスは、1つの関数で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
実行した手順のトラブルシューティング
アプリノート
上部のツールバーには、緑と赤の2つのボタンがあります。緑はテキストを左揃えにします。赤はテキストを中央に配置します。
下部のツールバーには5つのボタンがあります:巻き戻し、html、portrait、landscape、およびfast forward。 rewindボタンは、メインテーブルの高さを10px減らします。 早送りは高さを10px増やします。 htmlボタンはhtmlビューを表示します。 Portraitおよびlandscapeは、それぞれの方向でPDFを表示します。
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>
質問が投稿されてからしばらく経ちました。しかし、私はこれに興味をそそられ、なぜこれが起こるのかを理解しようとしていました。
また、これを確認するためにさまざまな組み合わせをテストしてみました。しかし、ネイティブiOSコードは役に立たないようです。しかし、autoの高さをbottom-tableに割り当てると、うまくいくように見えました。ただし、明示的な高さの設定は機能しませんでした。
table.bottom-table {
width: 1012px;
height: auto;
}
PDFレンダリング中は、PDFのフレームの設定で問題が発生した可能性がありますが、それ以外の場合は、PortraitとPortraitの両方で問題が解決しないこともご存知だと思います。高さが特定の制限を超えたときのランドスケープモード。