Bernd
Bernd

Reputation: 11493

Add UITapGestureRecognizer to UITextView without blocking textView touches

How can I add a UITapGestureRecognizer to a UITextView but still have the touches getting through to the UITextView as normal?

Currently as soon as I add a custom gesture to my textView it blocks the tap for UITextView default actions like positioning the cursor.

var tapTerm:UITapGestureRecognizer = UITapGestureRecognizer()

override func viewDidLoad() {
    tapTerm = UITapGestureRecognizer(target: self, action: "tapTextView:")
    textView.addGestureRecognizer(tapTerm)
}

func tapTextView(sender:UITapGestureRecognizer) {
    println("tapped term – but blocking the tap for textView :-/")
…
}

How can I process taps but keep any textView behaviour like cursor positioning as is?

Upvotes: 17

Views: 15125

Answers (4)

Zell B.
Zell B.

Reputation: 10286

To do that make your view controller adopt to UIGestureRecognizerDelegate and override should recognize simultaneously with gesture recognizer method like:

override func viewDidLoad() {
    tapTerm = UITapGestureRecognizer(target: self, action: "tapTextView:")
    tapTerm.delegate = self
    textView.addGestureRecognizer(tapTerm)
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

Upvotes: 35

Mert Köksal
Mert Köksal

Reputation: 901

Somehow I could not assign a delegate inside UIView so I came up with a button solution.

I insert a button that completely covers the textView and when tapped on textViewButton I do resign the button so textView shows.

 @IBAction func textViewTapped(_ sender: UIButton) {
        self.placeholderLabel.isHidden = true
        self.textViewButton.resignFirstResponder()
    }

Upvotes: 0

Frederick C. Lee
Frederick C. Lee

Reputation: 9503

Swift 4.2
The following steps allows me to escape a full-screen UITextView with a tap, whilst allowing to scroll the contents of the UITextView:

  1. Disconnected the UIGestureRecognizer from the UITableView.
  2. Made a CustomTextView: UITextView.
  3. Added a 'sender' var to the particular UIViewController with the CustomTextView.
  4. Trap for 'Touches Ended...'
  5. Call for an excape function within the sender UIViewController.

class CustomTextView: UITextView {
    var sender: DocViewController?

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let controller = sender {
            controller.handleSwipeGesture()
        }
    }
}

I can either scroll the contents of the UITextView or merely tap to exit.
The 'sender' is set from the hosting UIViewController at creation.

Upvotes: 1

Anish Kumar
Anish Kumar

Reputation: 1485

In case anyone came here looking for @Zell B.'s answer in Objective C, here's the code:

- (void)viewDidLoad {
    [super viewDidLoad];

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(textViewTapped:)];
    tap.delegate = self; 
    tap.numberOfTapsRequired = 1; 
   [self.textView addGestureRecognizer:tap];
}   

- (void)textViewTapped:(UITapGestureRecognizer *)tap {
    //DO SOMTHING 
}

#pragma mark - Gesture recognizer delegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES; 
}

PS: Don't forget < UIGestureRecognizerDelegate >

Upvotes: 5

Related Questions