0

When my user taps on my UITextView (NOT uitextfield...), an animation occurs. However after the UITextView begins editing, no other UITapGesture seems to be recognized (e.g. if I add a tapGesture to my UIView to dismiss this animation, it doesn't execute at all). I've been trying to fix this for what feels like forever. Help is appreciated, I'm stumped.

ViewController.m

 - (void)viewDidLoad 
        {
            [super viewDidLoad];

         self.replyField.delegate = self;

        [self.replyField setUserInteractionEnabled:YES];


        UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(textViewTapped)];
        [self.view addGestureRecognizer:gestureRecognizer];

        }

    -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

        return YES;

    }


    -(void)textViewTapped {
        NSLog(@"DISMISS PLEASE!");
        [self animateTextView:NO];

    }

       - (void)textViewDidBeginEditing:(UITextView *)textView
    {

        [self animateTextView: YES];
        self.replyField.gestureRecognizers = nil;


    }


    - (void)textViewDidEndEditing:(UITextView *)textView
    {
        [self animateTextView:NO];


    }


    - (void) animateTextView:(BOOL) up
    {
        const int movementDistance = 206;
        const float movementDuration = 0.3f;
        int movement= movement = (up ? -movementDistance : movementDistance);
        NSLog(@"%d",movement);

        [UIView beginAnimations: @"anim" context: nil];
        [UIView setAnimationBeginsFromCurrentState: YES];
        [UIView setAnimationDuration: movementDuration];
        self.view.frame = CGRectOffset(self.inputView.frame, 0, movement);
        [UIView commitAnimations];



    }


    - (void)textViewDidChange:(UITextView *)textView
    {

    }
Brittany
  • 1,351
  • 3
  • 22
  • 60
  • 1
    Try using `resignFirstResponder` in conjunction with `endEditing:` – Alejandro Iván Oct 22 '17 at 05:07
  • @AlejandroIván Tried it, no go :( – Brittany Oct 22 '17 at 05:29
  • `[self.replyField resignFirstResponder]`? – Alejandro Iván Oct 22 '17 at 05:31
  • are you certain that you are touching the view, as the gesture is added to the view, and the textView is not filling the view bounds? – Ayman Ibrahim Oct 22 '17 at 05:39
  • @AlejandroIván No dice. I actually can't tap on any other buttons either outside my textView without dismissing it? Is this normal? – Brittany Oct 22 '17 at 05:54
  • On a library I wrote for myself, I remember that I had to configure additional things to make it work. Check [this repo](https://github.com/alejandroivan/KeyboardHelper/blob/master/UIViewController%2BKeyboardHelper.m), lines 51-58. Maybe it helps you. – Alejandro Iván Oct 22 '17 at 05:58
  • @Brittany as you mentioned, you can't tap on any button till keyboard and textview is there, you can add `UITapGestureRecognizer` on your `self.view` using storyboard and create one action in your code, it will give you call once user will tap on view anywhere. – Buntylm Oct 22 '17 at 06:19
  • @Buntylm Added UITapGesture to my view via Storyboard and still, keyboard can't be dismissed on tap :/ – Brittany Oct 22 '17 at 08:11
  • @brittany See if you have added the tap gesture then first check is your function is view controller getting called ? If yes then "resignFirstResponder" from your "textView" – Buntylm Oct 22 '17 at 08:13
  • Are you still need help? – Blacky Nov 16 '17 at 09:55

5 Answers5

1

I have encountered similar issues use follow below code to dismiss keyboard by tapping anywhere on screen view. Hope will helpful to you.

Objective c

- (void)viewDidLoad 
{
    UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    [self.view addGestureRecognizer:gestureRecognizer];
    gestureRecognizer.cancelsTouchesInView = NO;

}
- (void)dismissKeyboard
{
     [self.view endEditing:YES];
}

Swift 4

func viewDidLoad() {
    let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard))
    view.addGestureRecognizer(gestureRecognizer)
    gestureRecognizer.cancelsTouchesInView = false
 }

func dismissKeyboard() {
    view.endEditing(true)
}
BuLB JoBs
  • 791
  • 3
  • 18
  • I ended up using this method and it works - but in this case, how can I shift my view up when the keyboard is revealed? – Brittany Nov 16 '17 at 20:59
1

Your problem is not related to gesture recognizer. Problem caused by line:

self.view.frame = CGRectOffset(self.inputView.frame, 0, movement);

You set frame for self.view from self.inputView with offset.

And when self.view size is changed, its subviews (including text view) may have positions out of superview bound. And UIView doesn't respond touch event if touch point is out of superview bounds. You can easily check this by setting background color for views and show they frames in log:

...
- (void) animateTextView:(BOOL) up
{
    NSLog(@"self.view state1:%@", self.view);
    NSLog(@"self.replyField state1:%@", self.replyField);
    self.view.backgroundColor = [UIColor redColor];
    self.replyField.backgroundColor = [UIColor blueColor];

    const int movementDistance = 206;
    const float movementDuration = 0.3f;
    int movement= movement = (up ? -movementDistance : movementDistance);
    NSLog(@"%d",movement);

    [UIView beginAnimations: @"anim" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    //self.view.frame = CGRectOffset(self.inputView.frame, 0, movement);
    self.replyField.frame = CGRectOffset(self.replyField.frame, 0, movement);
    [UIView setAnimationDidStopSelector:@selector(afterAnimationStops)];
    [UIView commitAnimations];
}

- (void)afterAnimationStops {
    NSLog(@"self.view state2:%@", self.view);
    NSLog(@"self.replyField state2:%@", self.replyField);
}
...

Also what is self.inputView? is it properly set?

BTW: What goal of the code? Do you want to move text view to avoid overlapping by keyboard? Then consider placing it in UIScrollView. e.g see discussion here: How to make a UITextField move up when keyboard is present?.

Vladimir
  • 7,164
  • 8
  • 23
  • 36
  • You're a genius. Lol. Thank you, this was driving me absolutely crazy! Fixed my code based on this. – Brittany Nov 16 '17 at 21:26
0

In ViewDidLoad :

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];

Create one method :

-(void)dismissKeyboard {

    [textView resignFirstResponder];
}
Miti
  • 119
  • 1
  • 7
0

Not clearly understand what you want BTW let me explain.

First of all if you want to hide your keyboard you can do it by single line code.

Objective C

[self.view endEditing:YES];

Swift

 view.endEditing(true)

Now in your code, you added tap gesture on self.view it means if you touch main view anywhere then your gesture method will be call. If you want that my keyboard will be hide when I touch on main view then in tap gesture's method you should write above code ([self.view endEditing:YES];) But make sure keyboard will be open if you tap on your textView.

But If you want keyboard should not open when I click on UITextView then there are many ways but follow below

Objective C

UIView* dummyInputView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];    
myTextView.inputView = dummyInputView;

Swift

let dummyInputView = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 1))
myTextView.inputView = dummyInputView

Here keyboard will not be open but cursor will be blinking if you want to hide cursor then you can do by below code

Objective C

 myTextView.tintColor = [UIColor clearColor];

Swift

 myTextView.tintColor = UIColor.clear

If you have any issue then do comment.

iPatel
  • 41,165
  • 13
  • 109
  • 131
-2

In viewController you can do this

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:Yes];
}
leeping
  • 11
  • 2