AirPrint打印WKWebView内容:双面打印设置不同边距的技术难题
解决WKWebView双面打印正反页不同边距的问题
我之前做项目时刚好碰到过一模一样的需求,折腾了好一阵才找到靠谱的方案,分享给你:
核心思路:重写UIPrintPageRenderer的分页可打印区域方法
你之前用了自定义UIPrintPageRenderer,但可能没注意到iOS 10+提供了一个按页设置可打印区域的方法——printableRect(forPageAt pageIndex: Int),这正是解决正反页不同边距的关键。我们可以通过这个方法,根据页码奇偶(对应正反页)返回不同的可打印区域,WKWebView的viewPrintFormatter会自动适配这个区域布局内容。
具体实现步骤
1. 自定义UIPrintPageRenderer子类
class DuplexPrintPageRenderer: UIPrintPageRenderer { // 定义正反页的边距(可根据需求调整) private let oddPageInsets = UIEdgeInsets(top: 40, left: 60, bottom: 40, right: 20) private let evenPageInsets = UIEdgeInsets(top: 40, left: 20, bottom: 40, right: 60) override func printableRect(forPageAt pageIndex: Int) -> CGRect { let paperRect = self.paperRect var currentInsets = oddPageInsets // 仅当开启双面打印时,才区分正反页边距 if let printInfo = self.printInfo, printInfo.duplex != .none { currentInsets = pageIndex % 2 == 0 ? oddPageInsets : evenPageInsets } return UIEdgeInsetsInsetRect(paperRect, currentInsets) } // 可选:如果需要正反页显示不同的页眉/页脚,重写以下方法 override func drawHeaderForPageAtIndex(_ pageIndex: Int, in headerRect: CGRect) { let pageText = "第 \(pageIndex + 1) 页" let textAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12)] // 根据页码调整页眉位置,匹配边距 let textX = headerRect.origin.x + (pageIndex % 2 == 0 ? oddPageInsets.left : evenPageInsets.left) let textRect = CGRect(x: textX, y: headerRect.origin.y, width: headerRect.width, height: headerRect.height) pageText.draw(in: textRect, withAttributes: textAttributes) } }
2. 结合WKWebView的打印Formatter使用
// 获取WKWebView的打印Formatter let webPrintFormatter = yourWKWebView.viewPrintFormatter() // 可选:设置web内容的内边距(如果需要) // webPrintFormatter.contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // 初始化自定义Renderer并添加Formatter let printRenderer = DuplexPrintPageRenderer() printRenderer.addPrintFormatter(webPrintFormatter, startingAtPageAt: 0) // 配置打印信息(开启双面打印) let printInfo = UIPrintInfo.printInfo() printInfo.duplex = .longEdge // 长边装订双面打印,.shortEdge为短边装订 printRenderer.printInfo = printInfo // 触发打印 let printController = UIPrintInteractionController.shared printController.printPageRenderer = printRenderer printController.present(animated: true) { _, success, error in if let error = error { print("打印出错:\(error.localizedDescription)") } }
关于你提到的其他疑问
- WKWebView的
viewPrintFormatter无法自定义?:确实不能直接重写这个Formatter,但我们不需要——通过自定义UIPrintPageRenderer的printableRect方法,就能间接控制Web内容的布局范围,Formatter会自动适配这个区域。 - 生成PDF的需求:如果需要先生成PDF再打印,同样可以用这个自定义Renderer来生成PDF数据:
func generateDuplexPDF() -> Data? { let renderer = DuplexPrintPageRenderer() renderer.addPrintFormatter(yourWKWebView.viewPrintFormatter(), startingAtPageAt: 0) let paperRect = UIPrintPageRenderer.defaultPaperRect() renderer.setValue(NSValue(cgRect: paperRect), forKey: "paperRect") return renderer.pdfData() }
这个方案完全基于系统API,不需要额外的第三方库,而且能完美适配双面打印的正反页边距需求。
内容的提问来源于stack exchange,提问作者vinayak vanjari
相关产品推荐
相关产品推荐

