0

I am creating a sketch or canvas editor using the Apple Pencil Kit and I want to add moveable, rotatable, and zoomable items (text, image, etc.) to canvas. When I use the Text element in SwiftUI and add Drag Gesture, Magnification Gesture, and Rotate Gesture, the drag gesture doesn't work simultaneously with the other gestures. So, I have decided to use UIViewRepresentable and create elements on the UIKit side. However, now I am unable to pan any items on the UIKit side. Please could you help me?

//
//  SwiftUIView.swift
//  Drawing
//
//  Created by Furkan Ergün on 24.01.2023.
//

import SwiftUI

struct PanLabel: UIViewRepresentable {
  @State private var position = CGSize.zero
  @State private var pointSize: CGFloat = 0
  
  func makeUIView(context: Context) -> UILabel {
    let label = UILabel()
    label.text = "Pan me!"
    label.font = UIFont.systemFont(ofSize: 30.0)
    label.backgroundColor = UIColor.green

    let panGesture = UIPanGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.panLabel(recognizer:)))
    label.isUserInteractionEnabled = true
    panGesture.delegate = context.coordinator
    label.addGestureRecognizer(panGesture)

    let pinchGesture = UIPinchGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.pinchLabel(gesture:)))
    label.addGestureRecognizer(pinchGesture)
    pinchGesture.delegate = context.coordinator

    let rotateGesture = UIRotationGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.rotateLabel(gesture:)))
    label.addGestureRecognizer(rotateGesture)
    rotateGesture.delegate = context.coordinator

    return label
  }
  
  
  func updateUIView(_ uiView: UILabel, context: Context) {
      
  }
  
  func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }
  
  class Coordinator: NSObject, UIGestureRecognizerDelegate {
    var parent: PanLabel
    
    init(_ parent: PanLabel) {
      self.parent = parent
    }
    
    open var isGestureEnabled = true
    
    // MARK: - gesture handle

    // location will jump when finger number change
    private var initPanFingerNumber:Int = 1
    private var isPanFingerNumberChangedInThisSession = false
    private var lastPanPoint:CGPoint = CGPoint(x: 0, y: 0)
    
    @objc func panLabel(recognizer: UIPanGestureRecognizer) {
      guard isGestureEnabled, let view = recognizer.view else { return }
              
              // init
              if recognizer.state == .began {
                  lastPanPoint = recognizer.location(in: view)
                  initPanFingerNumber = recognizer.numberOfTouches
                  isPanFingerNumberChangedInThisSession = false
              }
              
              // judge valid
              if recognizer.numberOfTouches != initPanFingerNumber {
                  isPanFingerNumberChangedInThisSession = true
              }
              
              if isPanFingerNumberChangedInThisSession {
                  return
              }
              
              // perform change
              let point = recognizer.location(in: view)
              view.transform = view.transform.translatedBy(x: point.x - lastPanPoint.x, y: point.y - lastPanPoint.y)
              lastPanPoint = recognizer.location(in: view)
    }
    
    @objc func pinchLabel(gesture: UIPinchGestureRecognizer) {
//      let label = gesture.view as! UILabel
//        
//      if gesture.state == .began {
//        let font = label.font
//        parent.pointSize = font!.pointSize
//        gesture.scale = label.font!.pointSize * 0.1
//      }
//    
//      if 1 <= gesture.scale && gesture.scale <= 10  {
//        label.font = UIFont.systemFont(ofSize: gesture.scale * 10)
//        
//        resizeLabelToText(textLabel: label)
//      }
//      gesture.scale = 1
    
    }
    
    @objc func rotateLabel(gesture: UIRotationGestureRecognizer) {
      let label = gesture.view as! UILabel
        
      switch gesture.state {
      case .changed:
        // Update label's transform
        label.transform = label.transform.rotated(by: gesture.rotation)
        gesture.rotation = 0
      default:
        break
      }
    
    }
    
    func resizeLabelToText(textLabel : UILabel) {
      let labelSize = textLabel.intrinsicContentSize
      textLabel.bounds.size = labelSize
    }
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
      return true
    }
  }
}


struct SwiftUIView: View {
  @State private var rotation: Double = 0
  @State private var offset: CGSize = .zero
  @State private var scale: CGFloat = 1
  
  var body: some View {
    
    VStack{
      PanLabel().frame(width: 50, height: 50)
      Spacer()
    }
  }
}

struct SwiftUIView_Previews: PreviewProvider {
  static var previews: some View {
    SwiftUIView()
  }
}

And also I tried this solution solution but I can't fit this for SwiftUI side.

0 Answers0