Search code examples
iosswiftpdfpdfviewios-pdfkit

How I can move/drag multiple views on pdf view?


What I am doing is that, I took pdf view, it contains one sample pdf. On top of that, I am adding more than 1 signatories(custom view) views, when user click on add button from navigation bar.

Scene 1: When add first Signatory view (customview) on pdf, it is adding add and I can drag/move that first Signatory view (Signatory1) on pdf, this is working fine.

Scene 2: When add second Signatory view (Signatory2 customview) on pdf, it is adding and I can drag/move that second Signatory view (Signatory2) on pdf, this is also working fine, but in this scenario I can't move/drag the first signatory view (Signatory1)

Scene 3: Similarly When add third Signatory view (Signatory3 customview) on pdf, it is adding and I can drag/move that third Signatory view (Signatory3) on pdf, this is also working fine, but in this scenario I can't move/drag the first signatory view (Signatory1) and second signatory view (Signatory2) and so on

The problem is that, I have access to only the current Signatory only (I can move/drag only the current Signatory view which added recently), I can can't able to move/drag old Signatories views.

How I can move/drag any Signatory, according to my choice when I click/touch (drag/move) any specific Signatory view on the pdf view ?

Here is the some code,

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    
        customView1 = SignatoryXibView(frame: CGRect(x: 30, y: 30, width: 112, height: 58))
        customView2 = SignatoryXibView(frame: CGRect(x: 30, y: 30, width: 112, height: 58))
        customView3 = SignatoryXibView(frame: CGRect(x: 30, y: 30, width: 112, height: 58))
        customView4 = SignatoryXibView(frame: CGRect(x: 30, y: 30, width: 112, height: 58))
        customView5 = SignatoryXibView(frame: CGRect(x: 30, y: 30, width: 112, height: 58))
        
        loadPdf()
    
    }
    
    func loadPdf(){
        
        if let path = Bundle.main.path(forResource: "appointment-letter", ofType: "pdf") {
            if let pdfDocument = PDFDocument(url: URL(fileURLWithPath: path)) {
                pdfView.displayMode =  .singlePage // .singlePage //.singlePageContinuous //.twoUp
                //by default display mode is - singlePageContinuous
                pdfView.autoScales = true
                pdfView.displayDirection = .vertical // .horizontal//.vertical
                pdfView.document = pdfDocument
            
                pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleTopMargin, .flexibleBottomMargin]
                pdfView.zoomIn(self)
                pdfView.autoScales = true
                pdfView.backgroundColor = UIColor.white

                //Imp line
                pdfView.usePageViewController(true, withViewOptions: [:])
                
                currentPageNumberOfPdf = self.pdfView.currentPage?.pageRef?.pageNumber ?? 0
                print("Total Pages in PDF : ",pdfDocument.pageCount);
                
                self.pdfView.bringSubviewToFront(customView1!)
            }
        }
        
    }

 @IBAction func addSignatoryButtonClicked(_ sender: Any) {
        
        signatoryCount = signatoryCount + 1
        
        if signatoryCount == 1 {
            customView1?.signatoryLabel.text = "Signatory \(signatoryCount)"
            self.pdfView.addSubview(customView1!)
        }
        else  if signatoryCount == 2 {
            customView2?.signatoryLabel.text = "Signatory \(signatoryCount)"
            self.pdfView.addSubview(customView2!)
        }
        else  if signatoryCount == 3 {
            customView3?.signatoryLabel.text = "Signatory \(signatoryCount)"
            self.pdfView.addSubview(customView3!)
        }
        else  if signatoryCount == 4 {
            customView4?.signatoryLabel.text = "Signatory \(signatoryCount)"
            self.pdfView.addSubview(customView4!)
        }
        else  if signatoryCount == 5 {
            customView5?.signatoryLabel.text = "Signatory \(signatoryCount)"
            self.pdfView.addSubview(customView5!)
        }
    }
    

    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        let touch = touches.first
        let touchLocation = touch?.location(in: self.pdfView)
       // customView1?.center =  touchLocation!
       
        
        if signatoryCount == 1 {
            customView1?.center = touchLocation!
            return
        }
        else  if signatoryCount == 2 {
            customView2?.center = touchLocation!
            return
        }
        else  if signatoryCount == 3 {
            customView3?.center = touchLocation!
            return
        }
        else  if signatoryCount == 4 {
            customView4?.center = touchLocation!
            return
        }
        else  if signatoryCount == 5 {
           customView5?.center = touchLocation!
           return
        }
    
       // frame = view.convert(customView1!.frame, from: pdfView)
       // print("touchesMoved \(frame!.dictionaryRepresentation)")
    
    }

Here is the complete project source code


Solution

  • You got pretty close. You just need to apply the same approach as I suggested in your last question but respecting the superview's frame.

    First add those helpers to your project:


    extension  CGPoint {
        static func +(lhs: CGPoint, rhs: CGPoint) -> CGPoint {
            .init(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
        }
        static func +=(lhs: inout CGPoint, rhs: CGPoint) {
            lhs.x += rhs.x
            lhs.y += rhs.y
        }
    }
    

    extension UIView {
        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)))
        }
    }
    

    Second just get rid of the pan gesture recognizer and the correspondent method in your ViewController.

    Third change your SignatoryXibView pan gesture to the one below. This will translate the center of the view and respect the frame of its superview:

    @objc func pan(_ gesture: UIPanGestureRecognizer) {
        translate(gesture.translation(in: self))
        gesture.setTranslation(.zero, in: self)
        setNeedsDisplay()
    }
    

    sample project