0

I have a UITextView that has a pan gesture recognizer so it is draggable around the screen. I am trying to disable this gesture recognizer while the text field is being edited so the text stays in the middle of the screen, and the user can't drag it below the keyboard.

I have tried answers like this and this but can't seem to get them to work. I've also tried removing the gesture recognizer using textField.removeGestureRecognizer(textField.panGestureRecognizer) but couldn't get that to work either. Does anyone know what is going wrong here?

Here is my code;

import UIKit

class ViewController: UIViewController, UIGestureRecognizerDelegate {

let textField = UITextView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 100))

//the current center of the text being edited
var currentCenter = CGPoint()


override func viewDidLoad() {
    super.viewDidLoad()

    // tap gesture recognizer for keyboard hide
    let HideKeyboardTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
    view.addGestureRecognizer(HideKeyboardTap)

    textField.text = "hello"
    textField.font = UIFont.systemFont(ofSize: 80)

    textField.textContainerInset = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)


    textField.sizeToFit()
    self.view.addSubview(textField)

    //Enable multiple touch and user interaction for textfield
    textField.isUserInteractionEnabled = true
    textField.isMultipleTouchEnabled = true

    //add pan gesture
    let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
    panGestureRecognizer.delegate = self
    textField.addGestureRecognizer(panGestureRecognizer)

    NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardShowNotification), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardHideNotification), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

}

@objc func dismissKeyboard() {
    view.endEditing(true)
}

@objc func handleKeyboardShowNotification(notification: NSNotification) {

    if let keyboardFrame: NSValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
        let keyboardRectangle = keyboardFrame.cgRectValue
        let keyboardHeight = keyboardRectangle.height

        currentCenter = textField.center
        textField.center = CGPoint(x: UIScreen.main.bounds.midX , y: UIScreen.main.bounds.height - (keyboardHeight + textField.bounds.height + 10))

        textField.panGestureRecognizer.isEnabled = false

    }
}


@objc func handleKeyboardHideNotification() {

    textField.panGestureRecognizer.isEnabled = true
    textField.center = currentCenter

}

@objc func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
    if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {

        let translation = gestureRecognizer.translation(in: self.view)
        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)
    }

}


}

Thanks for any help!

brontea
  • 555
  • 4
  • 14

2 Answers2

0

Instead of trying to disable the gesture, how about do nothing in the gesture action while editing?

@objc func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
    if(textField.isEditing){return;}
    if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {

        let translation = gestureRecognizer.translation(in: self.view)
        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)
    }

}
Ricky Mo
  • 6,285
  • 1
  • 14
  • 30
  • Good idea - I tried this and got an error saying 'value of type 'UITextView' has no member 'isEditing'' but it worked with isFirstResponder so thankyou! :) – brontea Dec 04 '18 at 01:58
0
    private func getPanGesture() -> [UIPanGestureRecognizer]? {
        let panGesture = textField.gestureRecognizers?.filter({$0 is UIPanGestureRecognizer})
        return panGesture as? [UIPanGestureRecognizer]
    }

    private func disablePanGesture() {
        let enabledGestures = getPanGesture()?.filter({$0.isEnabled})
        enabledGestures?.forEach({ (gesture) in
            gesture.isEnabled = false
        })
    }

    private func enablePanGesture() {
        let disabledGestures = getPanGesture()?.filter({!$0.isEnabled})
        disabledGestures?.forEach({ (gesture) in
            gesture.isEnabled = true
        })
    }
@objc func handleKeyboardShowNotification(notification: NSNotification) {

        if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
            ..
            disablePanGesture()
        }
    }


    @objc func handleKeyboardHideNotification() {
        enablePanGesture()
        ..
    }
prex
  • 719
  • 4
  • 17