Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to control top & bottom page margins when using UIMarkupTextPrintFormatter?

I'm trying to use the printing stuff in iOS 4.2 to print from my iPhone app, but I'm having real trouble getting multi-page content to display nicely. As you can see in the attached screenshots of PDFs generated through the iOS printing API, UIMarkupTextPrintFormatter really likes to use a painfully small top-margin when rendering.

Additionally, it doesn't seem to try to split block-elements too nicely either ... it's tough to see in the screenshot but the page break actually occurs halfway through a table row, rather than on a border between rows.

I've tried using the CSS @page directives to specify page boundaries, however iOS Webkit doesn't seem to support these at all.

Does anyone know of any techniques, either in HTML or through the iOS SDK to make these top-margins bigger?

I really don't want to write a custom UIPrintPageRenderer class because I'm trying to give my users the ability to customize their printouts through HTML templates ... going with a custom renderer would almost certainly make this impossible (or really difficult).

Any help is much appreciated!

Top-of-page are really small by default

like image 362
glenc Avatar asked Oct 24 '25 05:10

glenc


3 Answers

You're on the right track with UIPrintPageRenderer, but fortunately you don't need to write a custom subclass to do this. All you need to do is instantiate a vanilla UIPrintPageRenderer, set the headerHeight and footerHeight properties, and add your HTML formatter to the renderer using addPrintFormatter:startingAtPage:. It only takes a few extra lines of code, I have posted my method here: Print paper size and content inset

like image 125
tobygriffin Avatar answered Oct 26 '25 20:10

tobygriffin


Apple does not expose any official API

  • Remove or override default printer margins (also called "hardware margins" or "non-printable areas")
  • Enable full-bleed printing for standard page types like A4 or US Letter
  • Control the printableRect directly when using only UIPrintInteractionController with a UIPrintFormatter

You try to custom paperRect and printableRect

like

class FullPageRenderer: UIPrintPageRenderer {
let pageSize: CGSize

init(pageSize: CGSize) {
    self.pageSize = pageSize
    super.init()
    
    let printableRect = CGRect(origin: .zero, size: pageSize)
    let paperRect = CGRect(origin: .zero, size: pageSize)

    setValue(paperRect, forKey: "paperRect")
    setValue(printableRect, forKey: "printableRect")
}}

func generatePDFfromWebView(_ webView: WKWebView, fileName: String, pageSize: CGSize = CGSize(width: 595.2, height: 841.8)) { let printFormatter = webView.viewPrintFormatter()

let renderer = FullPageRenderer(pageSize: pageSize)
renderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)

let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, CGRect(origin: .zero, size: pageSize), nil)

for pageIndex in 0..<renderer.numberOfPages {
    UIGraphicsBeginPDFPage()
    renderer.drawPage(at: pageIndex, in: UIGraphicsGetPDFContextBounds())
}

UIGraphicsEndPDFContext()

// Save or share PDF
let url = FileManager.default.temporaryDirectory.appendingPathComponent(fileName + ".pdf")
try? pdfData.write(to: url)
print("PDF saved at: \(url)")

}

like image 26
Piyush Nagora Avatar answered Oct 26 '25 18:10

Piyush Nagora


You're on the right track with UIPrintPageRenderer, but fortunately you don't need to write a custom subclass to do this. All you need to do is instantiate a vanilla UIPrintPageRenderer, set the headerHeight and footerHeight properties, and add your HTML formatter to the renderer using addPrintFormatter:startingAtPage:. It only takes a few extra lines of code, I have posted my method here: Print paper size and content inset

like image 27
tobygriffin Avatar answered Oct 26 '25 18:10

tobygriffin