Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
215 views
in Technique[技术] by (71.8m points)

html - UIPrintPageRenderer breaks content on different pages and skips part of page

Im rendering pdf from html content with help of UIPrintPageRenderer, unfortunately sometimes occurs bug, when one element is divided on to parts on different pages. Is there any way to avoid id?

My code and screenshots below:

BUG SCREENSHOT

UIPrintPageRenderer inheritance to specify pdf details.

public class CustomPrintPageRenderer: UIPrintPageRenderer {
    fileprivate let offsetX: CGFloat = 40.0
    fileprivate let offsetY: CGFloat = 12.0
    fileprivate let kHeaderHeight: CGFloat = 36
    fileprivate let kFooterHeight: CGFloat = 36
    fileprivate let debugFrame = false
    
    fileprivate var name: String?
    fileprivate var policy: String?
    
    init(name: String, policy: String, content: String) {
        self.name = name
        self.policy = policy
        super.init()
        
        // Set the page frame.
        setValue(NSValue(cgRect: App.A4Rect), forKey: "paperRect")
        
        // Set the printing area frame.
        setValue(NSValue(cgRect: App.A4Rect.insetBy(dx: 0, dy: 0)), forKey: "printableRect")

        headerHeight = kHeaderHeight
        footerHeight = kFooterHeight
        
        // Create formatter
        let formatter = UIMarkupTextPrintFormatter(markupText: content)
        formatter.perPageContentInsets = UIEdgeInsets(top: kHeaderHeight + 15, left: 36, bottom: 0, right: 36)
        addPrintFormatter(formatter, startingAtPageAt: 0)
    }

    override public func drawHeaderForPage(at pageIndex: Int, in headerRect: CGRect) {
        if let name = name as NSString?, let policy = policy as NSString? {
            add(name: name, policy: policy, in: headerRect)
        }
        addLogo(in: headerRect)

        if debugFrame {
            let path = UIBezierPath(rect: headerRect)
            UIColor.red.set()
            path.stroke()
        }
    }
    
    override public func drawFooterForPage(at pageIndex: Int, in footerRect: CGRect) {
        addPageNumber(at: pageIndex, in: footerRect)
        
        if debugFrame {
            let path = UIBezierPath(rect: footerRect)
            UIColor.red.set()
            path.stroke()
        }
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// MARK: -

extension CustomPrintPageRenderer {
    fileprivate func addLogo(in headerRect: CGRect) {
        let image = #imageLiteral(resourceName: "mss-logo")
        let desiredHeight: CGFloat = 40
        let newWidth = (desiredHeight * image.size.width) / image.size.height
        
        let imageSize = CGSize(width: newWidth, height: desiredHeight)
        let imageRect = CGRect(
            x: headerRect.width - imageSize.width - offsetX,
            y: headerRect.height - imageSize.height + offsetY,
            width: imageSize.width,
            height: imageSize.height)
        image.draw(in: imageRect)
    }
    
    fileprivate func add(name: NSString, policy: NSString, in headerRect: CGRect) {
        let text = "(policy) - (name)"
        
        let font = UIFont(name: "HelveticaNeue", size: 12.0)
        let textSize = getTextSize(text: text as String, font: font!)
        
        let pointX = offsetX
        let pointY = headerRect.height - textSize.height
        
        let attributes = [NSAttributedStringKey.font: font!, NSAttributedStringKey.foregroundColor: Color.lightGray]
        
        text.draw(at: CGPoint(x: pointX, y: pointY), withAttributes: attributes)
    }

    fileprivate func addPageNumber(at pageIndex: Int, in footerRect: CGRect) {
        let footerText: NSString = "Page (pageIndex + 1) of (numberOfPages)" as NSString

        let font = UIFont(name: "HelveticaNeue", size: 12.0)
        let textSize = getTextSize(text: footerText as String, font: font!)
        
        let pointX = footerRect.width - textSize.width - offsetX
        let pointY = footerRect.origin.y + footerRect.height - textSize.height - 25
        
        let attributes = [NSAttributedStringKey.font: font!]
        
        footerText.draw(at: CGPoint(x: pointX, y: pointY), withAttributes: attributes)
    }
    
    fileprivate func getTextSize(text: String, font: UIFont!, textAttributes: [NSAttributedStringKey: AnyObject]! = nil) -> CGSize {
        let testLabel = UILabel(frame: CGRect(x: 0.0, y: 0.0, width: paperRect.width, height: footerHeight))
        if let attributes = textAttributes {
            testLabel.attributedText = NSAttributedString(string: text, attributes: attributes)
        }
        else {
            testLabel.text = text
            testLabel.font = font!
        }
        
        testLabel.sizeToFit()
        
        return testLabel.frame.size
    }
}

** Alert html **

HTML I use to compose alert and add it to pdf.

<tr>
    <td></td>
</tr>
<tr>
    <div>
    <td class="alert" colspan="2">#TEXT#</td>
    </div>
</tr>
<tr>
    <td></td>
</tr>

** And pdf drawing **

This is how I draw pdf with CustomPrintPageRenderer.

   fileprivate func drawPDFUsingPrintPageRenderer(printPageRenderer: UIPrintPageRenderer) -> NSData! {
       let data = NSMutableData()
       
       UIGraphicsBeginPDFContextToData(data, App.A4Rect, nil)
       
       for i in 0 ..< printPageRenderer.numberOfPages {
           UIGraphicsBeginPDFPage()
           printPageRenderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
       }

       UIGraphicsEndPDFContext()
       
       return data
   }

Will be much appreciated for any help!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...