Как отклонить клавиатуру для UITextView с клавишей возврата? - PullRequest
370 голосов
/ 01 апреля 2009

В библиотеке IB введение говорит нам, что при нажатии клавиши return клавиатура для UITextView исчезнет. Но на самом деле ключ return может действовать только как '\ n'.

Я могу добавить кнопку и использовать [txtView resignFirstResponder], чтобы скрыть клавиатуру.

Но есть ли способ добавить действие для клавиши return на клавиатуре, чтобы мне не нужно было добавлять UIButton?

Ответы [ 33 ]

480 голосов
/ 21 мая 2010

Подумал, что вместо этого выложу фрагмент:

Убедитесь, что вы заявили о поддержке протокола UITextViewDelegate.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {

    if([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }

    return YES;
}

Обновление Swift 4.0:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
        return false
    }
    return true
}
341 голосов
/ 01 апреля 2009

UITextView не имеет методов, которые будут вызываться, когда пользователь нажимает клавишу возврата. Если вы хотите, чтобы пользователь мог добавить только одну строку текста, используйте UITextField. Нажатие на возврат и скрытие клавиатуры для UITextView не соответствует указаниям интерфейса.

Даже тогда, если вы хотите сделать это, внедрите метод textView:shouldChangeTextInRange:replacementText: UITextViewDelegate и в этой проверке, если текст замены \n, скройте клавиатуру.

Могут быть и другие пути, но я не знаю ни одного.

73 голосов
/ 30 июня 2011

Я знаю, что на этот вопрос уже дан ответ, но мне не очень нравится использовать строковый литерал для новой строки, так что вот что я сделал.

- (BOOL)textView:(UITextView *)txtView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if( [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location == NSNotFound ) {
        return YES;
    }

    [txtView resignFirstResponder];
    return NO;
}

Обновление Swift 4.0:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text as NSString).rangeOfCharacter(from: CharacterSet.newlines).location == NSNotFound {
    return true
}
txtView.resignFirstResponder()
return false
}
42 голосов
/ 21 мая 2014

Я знаю, что на это уже много раз отвечали, но вот мои два цента на этот вопрос.

Я нашел ответы samvermette и ribeto очень полезными, а также комментарий maxpower в ответе ribeto, Но есть проблема с этими подходами. Проблема, о которой matt упоминает в ответе samvermette , заключается в том, что если пользователь хочет вставить что-то с разрывом строки внутри, клавиатура будет скрыта без вставки чего-либо.

Таким образом, мой подход представляет собой смесь трех вышеупомянутых решений и проверяет, является ли введенная строка новой строкой, когда длина строки равна 1, поэтому мы проверяем, что пользователь печатает вместо вставки.

Вот что я сделал:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    NSRange resultRange = [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch];
    if ([text length] == 1 && resultRange.location != NSNotFound) {
        [textView resignFirstResponder];
        return NO;
    }

    return YES;
}
35 голосов
/ 07 октября 2012

Более элегантный способ - убрать клавиатуру, когда пользователь нажимает где-то за рамкой клавиатуры.

Сначала установите представление ViewController для класса «UIControl» в инспекторе идентичности в UIBuilder. Удерживая клавишу «Control», перетащите представление в файл заголовка ViewController и свяжите его как действие с событием «Touch Up Inside», например:

ViewController.h

-(IBAction)dismissKeyboardOnTap:(id)sender;

В основном файле ViewController ViewController.m:

-(IBAction)dismissKeyboardOnTap:(id)sender
    {
         [[self view] endEditing:YES];
    }

Вы можете требовать двойного или длительного касания, используя аналогичные приемы. Возможно, вам понадобится установить ваш ViewController как UITextViewDelegate и подключить TextView к ViewController. Этот метод работает как для UITextView, так и для UITextField.

Источник: Ранчо Большого Ботаника

РЕДАКТИРОВАТЬ: Я также хотел бы добавить, что если вы используете UIScrollView, вышеупомянутый метод может работать не так легко через Interface Builder. В этом случае вы можете использовать UIGestureRecognizer и вызвать вместо него метод [[self view] endEditing: YES] внутри него. Примером может быть:

-(void)ViewDidLoad{
    ....
    UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc] 
        initWithTarget:self action:@selector(tap:)];
    [self.view addGestureRecognizer: tapRec];
    ....
}

-(void)tap:(UITapGestureRecognizer *)tapRec{
    [[self view] endEditing: YES];
}

Когда пользователь нажимает за пределами клавиатуры и не нажимает пробел, клавиатура отклоняется.

31 голосов
/ 24 февраля 2015

Добавьте этот метод в свой контроллер представления.

Swift

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
        return false
    }
    return true
}

Этот метод также может быть полезен для вас:

/**
Dismiss keyboard when tapped outside the keyboard or textView

:param: touches the touches
:param: event   the related event
*/
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    if let touch = touches.anyObject() as? UITouch {
        if touch.phase == UITouchPhase.Began {
            textField?.resignFirstResponder()
        }
    }
}
26 голосов
/ 05 июня 2012
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if([text isEqualToString:@"\n"])
        [textView resignFirstResponder];
    return YES;
}

yourtextView.delegate=self;

Также добавьте UITextViewDelegate

Не забудьте подтвердить протокол

Если вы не добавили if([text isEqualToString:@"\n"]), вы не можете редактировать

14 голосов
/ 23 сентября 2014

Существует другое решение при использовании с uitextview, Вы можете добавить панель инструментов как InputAccessoryView в «textViewShouldBeginEditing», и с помощью кнопки «Готово» на этой панели инструментов вы можете отклонить клавиатуру, код для этого следующий:

InDidLoad

toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)]; //toolbar is uitoolbar object
toolBar.barStyle = UIBarStyleBlackOpaque;
UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(btnClickedDone:)];
[toolBar setItems:[NSArray arrayWithObject:btnDone]];

В методе textviewdelegate

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
     [textView setInputAccessoryView:toolBar];
     return YES;
}

В действии кнопки «Готово», которая находится на панели инструментов, следующее:

-(IBAction)btnClickedDone:(id)sender
{
    [self.view endEditing:YES];
}
11 голосов
/ 11 августа 2017

Я нашел ответ josebama как наиболее полный и чистый ответ, доступный в этой теме.

Ниже приведен синтаксис Swift 4 для него:

func textView(_ textView: UITextView, shouldChangeTextIn _: NSRange, replacementText text: String) -> Bool {
    let resultRange = text.rangeOfCharacter(from: CharacterSet.newlines, options: .backwards)
    if text.count == 1 && resultRange != nil {
        textView.resignFirstResponder()
        // Do any additional stuff here
        return false
    }
    return true
}
6 голосов
/ 15 ноября 2011

Использование контроллера навигации для размещения панели для отклонения клавиатуры:

в файле .h:

UIBarButtonItem* dismissKeyboardButton;

в файле .m:

- (void)viewDidLoad {
    dismissKeyboardButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissKeyboard)];
}

-(void)textViewDidBeginEditing:(UITextView *)textView {
    self.navigationItem.rightBarButtonItem = dismissKeyboardButton;
}

-(void)textFieldDidBeginEditing:(UITextField *)textField {
    self.navigationItem.rightBarButtonItem = dismissKeyboardButton;
}

-(void)dismissKeyboard {
    [self.textField resignFirstResponder];
    [self.textView resignFirstResponder];
    //or replace this with your regular right button
    self.navigationItem.rightBarButtonItem = nil;
}
...