我建议PDFAnnotation
将UIView
内容添加到PDFView
.
由于它们的坐标系不同,因此比较 aUIView's
内的框架并不容易。PDFView
PDFAnnotation
在与 PDF 坐标系同步的作品中添加 aPDFView
在使用 UIView 时,您将需要在坐标空间之间进行一些转换,这可能会很棘手而且不太准确。

以下是我为使其与视图一起工作而进行的一些小改动。
首先在你SignatoryXibView
我添加了这个功能,当我们靠近边缘时显示一个红色边框
func showWarning(_ show: Bool)
{
if show
{
contentView1.layer.borderColor = UIColor.red.cgColor
return
}
contentView1.layer.borderColor = UIColor.green.cgColor
}
我认为SignatoryXibView
不应该负责检测和防止超出其超级视图范围,因此我创建了一个 ViewController 需要遵守的协议,以便它可以防止SignatoryXibView
超出PDFView
范围。
protocol SignatoryViewDelegate: class
{
func signatoryView(_ signatoryView: SignatoryXibView,
didReceivePanGesture gesture: UIPanGestureRecognizer)
}
class SignatoryXibView: UIView {
// Add this
weak var delegate: SignatoryViewDelegate?
// .. rest of your code
@objc
func pan(_ gesture: UIPanGestureRecognizer)
{
// Hand off view translation handling to the delegate
self.delegate?.signatoryView(self,
didReceivePanGesture: gesture)
}
}
现在在您的UIView
扩展程序中,您创建了一个效果很好的翻译方法,但是您不想翻译视图的位置。您要首先检查翻译是否会超出所需的边界并防止翻译发生。
extension UIView {
// Your original code
func translate(_ translation: CGPoint) {
let destination = center + translation
let minX = frame.width/2
let minY = frame.height/2
let maxX = superview!.frame.width-minX
let maxY = superview!.frame.height-minY
center = CGPoint(
x: min(maxX, max(minX, destination.x)),
y: min(maxY ,max(minY, destination.y)))
}
// I have added this function to return the new rect
// that would happen if this view translated
func translatedRect(_ translation: CGPoint) -> CGRect
{
// All of this is your calculation
let destination = center + translation
let minX = frame.width/2
let minY = frame.height/2
let maxX = superview!.frame.width-minX
let maxY = superview!.frame.height-minY
var rect = CGRect(origin: .zero,
size: CGSize(width: bounds.width,
height: bounds.height))
let midX = min(maxX, max(minX, destination.x))
let midY = min(maxY ,max(minY, destination.y))
// I am not translating here, just creating a new rect
// of the view if it would be translated
rect.origin = CGPoint(x: midX - frame.width/2,
y: midY - frame.height/2)
return rect
}
}
在您的ViewController's loadPDF()
函数中,使您的视图控制器成为SignatoryXibView
// Add Sign on PdfView
// Your code unchanged
let customView = SignatoryXibView(frame: CGRect(x: 150,
y: 140,
width: 112,
height: 58))
customView.signatoryLabel.text = "John Doe"
self.pdfView.addSubview(customView)
//Add this
customView.delegate = self
然后最后实现我们之前在协议中添加的委托函数,以防止SignatoryXibView
超出页面边界。
extension ViewController: SignatoryViewDelegate
{
func signatoryView(_ signatoryView: SignatoryXibView,
didReceivePanGesture gesture: UIPanGestureRecognizer)
{
// Get the location where the user has tapped
let gestureTouchLocation = gesture.translation(in: signatoryView)
// Get the new frame if the signature view would
// be translated
let updatedFrame
= signatoryView.translatedRect(gestureTouchLocation)
// Convert this rect from the Signature View's coordinate space
// To the PDFView's coordinate space
let updatedFrameConverted
= pdfView.convert(updatedFrame,
to: pdfView.currentPage!)
print("Updated frame: \(updatedFrame)")
print("Updated frame converted: \(updatedFrameConverted)")
print("Signature frame: \(signatoryView.frame)")
print()
// Retrieve the bounds of the current page
// Handle the optional properly in your production app
let pageRect = pdfView.currentPage!.bounds(for: .mediaBox)
// Check if the new frame of SignatoryXibView is within the bounds of the pdf page
if updatedFrameConverted.origin.x > CGFloat.zero &&
updatedFrameConverted.origin.y + updatedFrameConverted.height < pageRect.height &&
updatedFrameConverted.origin.x + updatedFrameConverted.width < pageRect.width &&
updatedFrameConverted.origin.y > CGFloat.zero
{
// Since the view is within the bounds, you can update the views frame
signatoryView.translate(gesture.translation(in: signatoryView))
gesture.setTranslation(.zero, in: signatoryView)
signatoryView.setNeedsDisplay()
// Do not show any warning
signatoryView.showWarning(false)
return
}
// The view has reached the edge of the page so do not perform any view
// translation and show the warning
signatoryView.showWarning(true)
}
}
最终结果应该为您提供以下结果,它可以防止视图超出页面边界并使视图变为红色以显示它无法进一步:

最后的想法
- 我建议
PDFAnnotation
在向 PDF 添加内容时使用
- 这将正确缩放和滚动页面,尤其是在缩放 PDF 等场景中,您可能需要再次更新视图以使其位于正确的位置
更新
func signatoryView
我在函数中更新了一些数学extension ViewController: SignatoryViewDelegate
在确定正确的边界方面,这应该会给您带来更好的结果,并且在您缩放时它也会起作用:

但是,由于它不是作为注释添加的,因此它不会随页面滚动,但在下一页上会观察到相同的边界。