Reputation: 63
I'm using PDFKit on iOS to highlight texts (PDF file). I do it by create a PDFAnnotation and add it to the selected text area. I want to highlight precisely the selected area but it always covers the whole line like the pics below. How can I create the annotation for the selected area only??
My code:
let highlight = PDFAnnotation(bounds: selectionText.bounds(for: page), forType: PDFAnnotationSubtype.highlight, withProperties: nil)
highlight.color = highlightColor
page.addAnnotation(highlight)
Upvotes: 4
Views: 2950
Reputation: 991
As suggested in PDFKit Highlight Annotation: quadrilateralPoints you can use quadrilateralPoints
to add different lines highlights to the same annotation.
func highlight() {
guard let selection = pdfView.currentSelection, let currentPage = pdfView.currentPage else {return}
let selectionBounds = selection.bounds(for: currentPage)
let lineSelections = selection.selectionsByLine()
let highlightAnnotation = PDFAnnotation(bounds: selectionBounds, forType: PDFAnnotationSubtype.highlight, withProperties: nil)
highlightAnnotation.quadrilateralPoints = [NSValue]()
for (index, lineSelection) in lineSelections.enumerated() {
let n = index * 4
let bounds = lineSelection.bounds(for: pdfView.currentPage!)
let convertedBounds = bounds.convert(to: selectionBounds.origin)
highlightAnnotation.quadrilateralPoints?.insert(NSValue(cgPoint: convertedBounds.topLeft), at: 0 + n)
highlightAnnotation.quadrilateralPoints?.insert(NSValue(cgPoint: convertedBounds.topRight), at: 1 + n)
highlightAnnotation.quadrilateralPoints?.insert(NSValue(cgPoint: convertedBounds.bottomLeft), at: 2 + n)
highlightAnnotation.quadrilateralPoints?.insert(NSValue(cgPoint: convertedBounds.bottomRight), at: 3 + n)
}
pdfView.currentPage?.addAnnotation(highlightAnnotation)
}
extension CGRect {
var topLeft: CGPoint {
get {
return CGPoint(x: self.origin.x, y: self.origin.y + self.height)
}
}
var topRight: CGPoint {
get {
return CGPoint(x: self.origin.x + self.width, y: self.origin.y + self.height)
}
}
var bottomLeft: CGPoint {
get {
return CGPoint(x: self.origin.x, y: self.origin.y)
}
}
func convert(to origin: CGPoint) -> CGRect {
return CGRect(x: self.origin.x - origin.x, y: self.origin.y - origin.y, width: self.width, height: self.height)
}
}
Upvotes: 6
Reputation: 495
PDFSelection
bounds(forPage:)
method returns one rectangle to satisfy whole selection area. Is not the best solution in your case.
Try with selectionsByLine()
, and add individual annotation for every rect, representing every single selected line in PDF. Example:
let selections = pdfView.currentSelection?.selectionsByLine()
// Simple scenario, assuming your pdf is single-page.
guard let page = selections?.first?.pages.first else { return }
selections?.forEach({ selection in
let highlight = PDFAnnotation(bounds: selection.bounds(for: page), forType: .highlight, withProperties: nil)
highlight.endLineStyle = .square
highlight.color = UIColor.orange.withAlphaComponent(0.5)
page.addAnnotation(highlight)
})
Upvotes: 4