How to dismiss keyboard for UITextView with return key?

Viewed 320866

In IB's library, the introduction tells us that when the return key is pressed, the keyboard for UITextView will disappear. But actually the return key can only act as '\n'.

I can add a button and use [txtView resignFirstResponder] to hide the keyboard.

But is there a way to add the action for the return key in keyboard so that I needn't add UIButton?

34 Answers

UITextView does not have any methods which will be called when the user hits the return key. If you want the user to be able to add only one line of text, use a UITextField. Hitting the return and hiding the keyboard for a UITextView does not follow the interface guidelines.

Even then if you want to do this, implement the textView:shouldChangeTextInRange:replacementText: method of UITextViewDelegate and in that check if the replacement text is \n, hide the keyboard.

There might be other ways but I am not aware of any.

Simular to other answers using the UITextViewDelegate but a newer swift interface isNewline would be:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if let character = text.first, character.isNewline {
        textView.resignFirstResponder()
        return false
    }
    return true
}

Just like matt comment to samvermette, I don't like the idea of detecting "\n" either. The "return" key is there for a reason in UITextView, that is to go to next line of course.

The best solution in my opinion is to mimic iPhone message app - which is to add toolbar (and button) on the keyboard.

I got code from following blog post:

http://www.iosdevnotes.com/2011/02/iphone-keyboard-toolbar/

Steps:

-Add toolbar to your XIB file - set the height to 460

-Add toolbar button item (if not already added). If you need to right-align it, also add flexible bar button item to XIB, and move the toolbar button item

-Create action that link your button item to resignFirstResponder as follow:

- (IBAction)hideKeyboard:(id)sender {
    [yourUITextView resignFirstResponder];
}

-Then:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification *)notification {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];

    CGRect frame = self.keyboardToolbar.frame;
    frame.origin.y = self.view.frame.size.height - 260.0;
    self.keyboardToolbar.frame = frame;

    [UIView commitAnimations];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];

    CGRect frame = self.keyboardToolbar.frame;
    frame.origin.y = self.view.frame.size.height;
    self.keyboardToolbar.frame = frame;

    [UIView commitAnimations];
}

You should add UIToolbar to top UITextView to make easy rather than using shouldChangeTextIn

In Swift 4

let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
        toolbar.barStyle = .default
        toolbar.items = [
            UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
            UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(doneAction))
        ]
        textView.inputAccessoryView = toolbar
@objc func doneAction(){
 self.textView.resignFirstResponder()
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField; // called from textfield (keyboard)

-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; // good tester function - thanks
Related