You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:02:45