ios How to make UITextView detect one tap?
Asked Answered
D

3

11
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"touchesBegan");

    //test
    UITouch *touch = [event allTouches] anyObject];
    if ([touch tapCount] == 2) {
        NSLog (@"tapcount 2");
        [self.textview becomeFirstResponder];

    }   

     else if ([touch tapCount] == 1) {
         NSLog (@"tapcount 1");
         [self.textview becomeFirstResponder];
         [self.view performSelector:@selector(select:)];


     }

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
    NSLog(@"touchesMoved");
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"****touchesEnded");
    [self.nextResponder touchesEnded: touches withEvent:event]; 
    NSLog(@"****touchesEnded");
    [super touchesEnded:touches withEvent:event];
    NSLog(@"****touchesEnded");
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesCancelled:touches withEvent:event]; 
    NSLog(@"touchesCancelled");
}

MY QUESTION:

I want to simulate two taps when tapping once on a UITextView, which is textview in this code. But I do not get NSLog from one and two taps when I tap either once or twice on textview, only outside it. What should I do to make it work?

Donau answered 25/11, 2011 at 15:29 Comment(2)
First of all this code would have to be in a custom UITextView subclass to work, and would likely interfere with normal operation. Secondly, what do you mean by "I want to simulate two taps when tapping once on a UITextView", I mean for what purpose?Muro
@Muro I want to give users an option to choose between one or two taps for a certain function. I want simulate two taps to get the selected text and make it only one tap for users if they choose this option. Is it possible to force forth two taps when tapping once on UITextView? bensnider's solution works perfectly. But how to simulate two taps?Donau
X
18

Probably I would use two gesture recognizers here.

//...some stuff above here probably in you're controllers viewDidLoad

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapRecognized:)];
singleTap.numberOfTapsRequired = 1;
[someTextView addGestureRecognizer:singleTap];
[singleTap release];

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapRecognized:)];
doubleTap.numberOfTapsRequired = 2;
[someTextView addGestureRecognizer:doubleTap];
[doubleTap release];

And the selectors would just be like:

- (void)singleTapRecognized:(UIGestureRecognizer *)gestureRecognizer {
    NSLog(@"single tap");
    // ...etc
}

- (void)doubleTapRecognized:(UIGestureRecognizer *)gestureRecognizer {
    NSLog(@"double tap");
    // ...etc
}
Xerophthalmia answered 25/11, 2011 at 16:10 Comment(2)
Your solution works expectantly perfect. However, I really want to simulate two taps when tapping once in order to get the selected text.Donau
What do you mean by, get the selected text?Muro
N
2

I encountered a similar issue where I wanted to capture a tap on a textView without editing the underlying text.

This answer is for Swift 3.0.

For my solution, I implemented the textView delegate method textViewShouldBeginEditing and returned false for the value. This allows me to capture taps on the textView without any additional overhead.

extension ViewController: UITextViewDelegate {
    func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
        // Do something

        return false
    }
}

Just be sure to assign the textView to use the delegate in your ViewController class.

Nils answered 18/11, 2016 at 19:53 Comment(0)
F
1

I had the same problem and the other answers did not work for me. So this is what I did.

I attached the gesture like another answer suggested. Then I made sure the delegate method for selection was called. I did try simply selecting the cell but that did not fire the delegate method. I believe that only user interactions cause the delegate method to be called, so this code mimics that behavior.

https://gist.github.com/brennanMKE/e89bf7a28d96812d6a22

@implementation TappableTextView

- (instancetype)init {
    self = [super init];
    if (self) {
        [self setup];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        [self setup];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}

- (void)setup {
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapRecognized:)];
    singleTap.numberOfTapsRequired = 1;
    [self addGestureRecognizer:singleTap];
}

- (void)singleTapRecognized:(id)sender {
    UIView *superview = self.superview;

    UICollectionViewCell *cell = nil;
    NSIndexPath *indexPath = nil;

    while (superview) {
        if ([superview isKindOfClass:[UICollectionViewCell class]]) {
            cell = (UICollectionViewCell *)superview;
        }

        if ([superview isKindOfClass:[UICollectionView class]] && cell) {
            UICollectionView *collectionView = (UICollectionView *)superview;
            indexPath = [collectionView indexPathForCell:cell];
            NSAssert(collectionView.delegate, @"Delegate must be defined");
            NSAssert([collectionView.delegate respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)], @"Selection must be supported");
            if (indexPath && [collectionView.delegate respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)]) {
                [collectionView.delegate collectionView:collectionView didSelectItemAtIndexPath:indexPath];
            }

            return;
        }

        superview = superview.superview;
    }
}

@end
Fourdrinier answered 31/7, 2014 at 2:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.