Zusammendrücken, Schwenken und Drehen von Text Gleichzeitig wie Snapchat [SWIFT 3]

Ich versuche, mich ein TextView, dass Sie sich bewegen kann, wie snapchat funktioniert. Ich habe etwas ähnlich, obwohl, wenn Sie versuchen und zu skalieren, während Sie rotiert, neigt sich zu Strecken horizontal unendlich und ziehen kann ein wenig buggy zu Zeiten.

Habe ich dieses:

func panGesture(pan: UIPanGestureRecognizer) {
    print("Being Dragged")
    if pan.state == .began {
        textViewOrigin = pan.location(in: textView)
    }else {
        let location = pan.location(in: view) //get pan location
        textView.frame.origin = CGPoint(x: location.x - textViewOrigin.x, y: location.y - textViewOrigin.y)
    }
}
func scaleGesture(_ gesture: UIPinchGestureRecognizer){
    print("Being Scaled")
    switch gesture.state{
    case.began:
        identity = textView.transform
    case.changed,.ended:
        textView.transform = identity.scaledBy(x: gesture.scale, y: gesture.scale)
    default:
        break
    }
}
func rotationGesture(sender: UIRotationGestureRecognizer){
    print("Being Rotated")
    textView.transform = textView.transform.rotated(by: sender.rotation)
    sender.rotation = 0
}

und ich bin versucht, dies zu erreichen:
Zusammendrücken, Schwenken und Drehen von Text Gleichzeitig wie Snapchat [SWIFT 3]

Wenn jemand helfen könnte, verändern oder neu schreiben, damit mein code, wäre Super, danke im Voraus!

InformationsquelleAutor Skiddswarmik | 2017-07-30



2 Replies
  1. 22

    Standardmäßig nach einer gestik-Erkennung auf einen Blick, beginnt die Handhabung der Geste, andere Merkmale werden ignoriert. Dieses Verhalten kann gesteuert werden, durch überschreiben der Methode (für Swift):

    gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)

    true zurück. Die default-Implementierung gibt false zurück. Um die Funktion überschreiben, fügen Sie einfach Ihre Umsetzung, Rückgabe von true, um Ihre ViewController-source-code-Datei.

    Ist hier einige Beispiel-Swift-code (siehe https://developer.apple.com/documentation/uikit/uigesturerecognizerdelegate/1624208-gesturerecognizer?changes=_7):

    class ViewController: UIViewController,UIGestureRecognizerDelegate {
    
        @IBOutlet var textField: UITextField!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            //Do any additional setup after loading the view, typically from a nib.
    
            //add pan gesture
            let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
            gestureRecognizer.delegate = self
            textField.addGestureRecognizer(gestureRecognizer)
    
            //Enable multiple touch and user interaction for textfield
            textField.isUserInteractionEnabled = true
            textField.isMultipleTouchEnabled = true
    
            //add pinch gesture
            let pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(pinchRecognized(pinch:)))
            pinchGesture.delegate = self
            textField.addGestureRecognizer(pinchGesture)
    
            //add rotate gesture.
            let rotate = UIRotationGestureRecognizer.init(target: self, action: #selector(handleRotate(recognizer:)))
            rotate.delegate = self
            textField.addGestureRecognizer(rotate)
    
    
        }
    
        func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
            if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
    
                let translation = gestureRecognizer.translation(in: self.view)
                //note: 'view' is optional and need to be unwrapped
                gestureRecognizer.view!.center = CGPoint(x: gestureRecognizer.view!.center.x + translation.x, y: gestureRecognizer.view!.center.y + translation.y)
                gestureRecognizer.setTranslation(CGPoint.zero, in: self.view)
            }
    
        }
    
        func pinchRecognized(pinch: UIPinchGestureRecognizer) {
    
            if let view = pinch.view {
                view.transform = view.transform.scaledBy(x: pinch.scale, y: pinch.scale)
                pinch.scale = 1
            }
        }
    
        func handleRotate(recognizer : UIRotationGestureRecognizer) {
            if let view = recognizer.view {
                view.transform = view.transform.rotated(by: recognizer.rotation)
                recognizer.rotation = 0
            }
        }
    
        //MARK:- UIGestureRecognizerDelegate Methods
        func gestureRecognizer(_: UIGestureRecognizer,
            shouldRecognizeSimultaneouslyWith shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
            return true
        }
    }

    In Objective C die überschreiben Funktion ist (siehe https://developer.apple.com/documentation/uikit/uigesturerecognizerdelegate/1624208-gesturerecognizer?language=objc):

    -(BOOL)gestureRecognizer:(UIGestureRecognizer*)aR1 shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)aR2
        {
        return YES;
        }
    • Wenn Sie mit dieser in swift 4 müssen Sie @objc vor jeder Griff-Funktion. Erklärung. Es verwendet, um implizit gefolgert werden, bevor swift 4.
    • Wenn Sie wollte, um zu erfassen die Koordinaten/Größe/Drehung/etc, so konnte Sie es dementsprechend auf einen post oder was auch immer, ähnlich wie Snapchat, wie würden Sie das tun?
    • für mich textfield dreht sich nicht aber pan-Geste funktioniert
    • Bagdiya können Sie bitte objective-c-code?
  2. 4

    Ich Schreibe eine Klasse für die einfache Verwendung.

    Grundlegende Verwendung:

    //define 
    var snapGesture: SnapGesture?
    
    //add gesture
    self.snapGesture = SnapGesture(view: self.testView!)
    
    //remove gesture
    self.snapGesture = nil

    Fortgeschrittene, für das Szenario, dass die Sicht empfangende Geste hintergrund-Ansicht:

    //add gesture
    self.snapGesture = SnapGesture(transformView: self.testView!, gestureView: self.view)
    
    //remove gesture
    self.snapGesture = nil

    Klasse:

    import UIKit
    
    /*
     usage:
    
        add gesture:
            yourObjToStoreMe.snapGesture = SnapGesture(view: your_view)
        remove gesture:
            yourObjToStoreMe.snapGesture = nil
        disable gesture:
            yourObjToStoreMe.snapGesture.isGestureEnabled = false
        advanced usage:
            view to receive gesture(usually superview) is different from view to be transformed,
            thus you can zoom the view even if it is too small to be touched.
            yourObjToStoreMe.snapGesture = SnapGesture(transformView: your_view_to_transform, gestureView: your_view_to_recieve_gesture)
    
     */
    
    class SnapGesture: NSObject, UIGestureRecognizerDelegate {
    
        //MARK: - init and deinit
        convenience init(view: UIView) {
            self.init(transformView: view, gestureView: view)
        }
        init(transformView: UIView, gestureView: UIView) {
            super.init()
    
            self.addGestures(v: gestureView)
            self.weakTransformView = transformView
        }
        deinit {
            self.cleanGesture()
        }
    
        //MARK: - private method
        private weak var weakGestureView: UIView?
        private weak var weakTransformView: UIView?
    
        private var panGesture: UIPanGestureRecognizer?
        private var pinchGesture: UIPinchGestureRecognizer?
        private var rotationGesture: UIRotationGestureRecognizer?
    
        private func addGestures(v: UIView) {
    
            panGesture = UIPanGestureRecognizer(target: self, action: #selector(panProcess(_:)))
            v.isUserInteractionEnabled = true
            panGesture?.delegate = self     //for simultaneous recog
            v.addGestureRecognizer(panGesture!)
    
            pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(pinchProcess(_:)))
            //view.isUserInteractionEnabled = true
            pinchGesture?.delegate = self   //for simultaneous recog
            v.addGestureRecognizer(pinchGesture!)
    
            rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotationProcess(_:)))
            rotationGesture?.delegate = self
            v.addGestureRecognizer(rotationGesture!)
    
            self.weakGestureView = v
        }
    
        private func cleanGesture() {
            if let view = self.weakGestureView {
                //for recognizer in view.gestureRecognizers ?? [] {
                //   view.removeGestureRecognizer(recognizer)
                //}
                if panGesture != nil {
                    view.removeGestureRecognizer(panGesture!)
                    panGesture = nil
                }
                if pinchGesture != nil {
                    view.removeGestureRecognizer(pinchGesture!)
                    pinchGesture = nil
                }
                if rotationGesture != nil {
                    view.removeGestureRecognizer(rotationGesture!)
                    rotationGesture = nil
                }
            }
            self.weakGestureView = nil
            self.weakTransformView = nil
        }
    
    
    
    
        //MARK: - API
    
        private func setView(view:UIView?) {
            self.setTransformView(view, gestgureView: view)
        }
    
        private func setTransformView(_ transformView: UIView?, gestgureView:UIView?) {
            self.cleanGesture()
    
            if let v = gestgureView  {
                self.addGestures(v: v)
            }
            self.weakTransformView = transformView
        }
    
        open func resetViewPosition() {
            UIView.animate(withDuration: 0.4) {
                self.weakTransformView?.transform = CGAffineTransform.identity
            }
        }
    
        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 panProcess(_ recognizer:UIPanGestureRecognizer) {
            if isGestureEnabled {
                //guard let view = recognizer.view else { return }
                guard let view = self.weakTransformView 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)
            }
        }
    
    
    
        private var lastScale:CGFloat = 1.0
        private var lastPinchPoint:CGPoint = CGPoint(x: 0, y: 0)
        @objc func pinchProcess(_ recognizer:UIPinchGestureRecognizer) {
            if isGestureEnabled {
                guard let view = self.weakTransformView else { return }
    
                //init
                if recognizer.state == .began {
                    lastScale = 1.0;
                    lastPinchPoint = recognizer.location(in: view)
                }
    
                //judge valid
                if recognizer.numberOfTouches < 2 {
                    lastPinchPoint = recognizer.location(in: view)
                    return
                }
    
                //Scale
                let scale = 1.0 - (lastScale - recognizer.scale);
                view.transform = view.transform.scaledBy(x: scale, y: scale)
                lastScale = recognizer.scale;
    
                //Translate
                let point = recognizer.location(in: view)
                view.transform = view.transform.translatedBy(x: point.x - lastPinchPoint.x, y: point.y - lastPinchPoint.y)
                lastPinchPoint = recognizer.location(in: view)
            }
        }
    
    
        @objc func rotationProcess(_ recognizer: UIRotationGestureRecognizer) {
            if isGestureEnabled {
                guard let view = self.weakTransformView else { return }
    
                view.transform = view.transform.rotated(by: recognizer.rotation)
                recognizer.rotation = 0
            }
        }
    
    
        //MARK:- UIGestureRecognizerDelegate Methods
        func gestureRecognizer(_: UIGestureRecognizer,
                               shouldRecognizeSimultaneouslyWith shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
            return true
        }
    
    }

    Nun, werden Sie diesen Punkt erreichen, fahren Sie bitte Fort.
    wie Sie wissen, ist die Geste in superView Essen Veranstaltung der Untersicht und in snapchat Beispiel die Geste Essen-Ereignis der Symbolleiste, wir müssen verhindern, dass jede Geste der Anerkennung von superview, wenn wir das berühren der Symbolleiste.

    Die Idee ist, fügen Sie ein pseduo angepasste Geste auf die Symbolleiste, so dass jede Geste wird verhindert, superview, und diese pseduo Geste, die nichts aber tun, liefern Sie die Geste oder ein Ereignis zu Untersichten oder seine eigene Ansicht.

    Hier, ich Schreibe auch eine Klasse für einfach zu bedienen.

    Verwendung:

       toolbarView.addGestureRecognizer(SnapBlockGestureRecognizer)

    Umsetzung:

    import UIKit
    
    class SnapBlockGestureRecognizer: UIGestureRecognizer {
    
        init() {
            //self.init(target: self, action: #selector(__dummyAction))
            super.init(target: nil, action: nil)
    
            self.addTarget(self, action: #selector(__dummyAction))
            self.cancelsTouchesInView = false
        }
    
        override init(target: Any?, action: Selector?) {
            super.init(target: target, action: action)
    
            self.cancelsTouchesInView = false
        }
    
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
            if self.state == .possible {
                self.state = .began
            }
        }
    
        override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        }
    
        override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
            self.state = .recognized
        }
    
        override func canBePrevented(by preventingGestureRecognizer: UIGestureRecognizer) -> Bool {
            return self.isGestureRecognizerAllowed(gr:preventingGestureRecognizer)
        }
    
    
        override func canPrevent(_ preventedGestureRecognizer: UIGestureRecognizer) -> Bool {
            return !(self.isGestureRecognizerAllowed(gr: preventedGestureRecognizer))
        }
    
        override func shouldBeRequiredToFail(by otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return !(self.isGestureRecognizerAllowed(gr: otherGestureRecognizer))
        }
    
        override func shouldRequireFailure(of otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return false
        }
    
        func isGestureRecognizerAllowed(gr: UIGestureRecognizer) -> Bool {
            return gr.view!.isDescendant(of: self.view!)
        }
    
        @objc func __dummyAction() {
            //do nothing
            //print("dummyAction")
        }
    }

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.