Как уволить клавиатуру для UITextView с помощью клавиши возврата?

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

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

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

30 ответов


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

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

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


подумал, что я бы разместил фрагмент прямо здесь:

убедитесь, что вы объявили о поддержке 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
}

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

- (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
}

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

Я нашел ответы samvermette и ribeto действительно полезно, а также комментарий по maxpower на ribeto'ы ответ. Но с этими подходами есть проблема. Проблема, что матовая упоминает в 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;
}

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

во-первых, установите представление ViewController в класс "UIControl" в инспекторе удостоверений в UIBuilder. Control-перетащите представление в файл заголовка ViewController и свяжите его как действие с событием, как Touch Up внутри, например:

ViewController.h

-(IBAction)dismissKeyboardOnTap:(id)sender;

в главном файле ViewController, Файл ViewController.м:

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

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

Источник: Big Nerd Ranch

EDIT: я также хотел бы добавить, что если вы используете UIScrollView, вышеуказанный метод может работать не так легко через построитель интерфейса. В таком случае, вы можете использовать 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];
}

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


добавьте этот метод в контроллер вида.

Свифт:

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()
        }
    }
}

-(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"]) вы не можете редактировать


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

в viewDidLoad

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];
}

Я нашел ответ josebama наиболее полное и чистое ответить в этой теме.

ниже Swift 3 синтаксис для этого:

func textView(_ textView: UITextView, shouldChangeTextIn _: NSRange, replacementText text: String) -> Bool {
    let resultRange = text.rangeOfCharacter(from: CharacterSet.newlines, options: .backwards)
    if text.characters.count == 1 && resultRange != nil {
        textView.resignFirstResponder()
        // Do any additional stuff here
        return false
    }
    return true
}

Так же, как Мэтт комментарий к samvermette, мне не нравится идея обнаружения "\n". Ключ "return" есть по какой-то причине в UITextView, то есть перейти к следующей строке, конечно.

лучшим решением, на мой взгляд, является имитация приложения iPhone message - добавление панели инструментов (и кнопки) на клавиатуре.

Я получил код из следующего сообщения в блоге:

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

действия:

- добавить панель инструментов в файл XIB-установите высоту 460

- добавить элемент кнопки панели инструментов (если он еще не добавлен). Если вам нужно выровнять его справа, также добавьте гибкий элемент кнопки панели в XIB и переместите элемент кнопки панели инструментов

- создайте действие, которое свяжет ваш элемент кнопки с resignFirstResponder как следуйте:

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

просто решил эту проблему другим способом.

  • создать кнопку, которая будет размещена в фоновом режиме
  • из инспектора атрибутов измените тип кнопки на пользовательский, и кнопка станет прозрачной.
  • разверните кнопку, чтобы охватить весь вид, и убедитесь, что кнопка находится позади всех остальных объектов. Простой способ сделать это-перетащить кнопку в верхнюю часть списка в представлении
  • Control перетащите кнопку, чтобы the viewController.h файл и создать действие (отправленное событие: коснитесь внутри), как:

    (IBAction)ExitKeyboard:(id)sender;
    
  • на ViewController.m должен выглядеть так :

    (IBAction)ExitKeyboard:(id)sender {
        [self.view endEditing:TRUE];
    }
    
  • запустите приложение, и когда вы щелкаете от TextView, клавиатура исчезает

добавить наблюдателя в viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(textViewKeyPressed:) name: UITextViewTextDidChangeNotification object: nil];

а затем используйте селектор для проверки "\n"

-(void) textViewKeyPressed: (NSNotification*) notification {

  if ([[[notification object] text] hasSuffix:@"\n"])
  {
    [[notification object] resignFirstResponder];
  }
}

он использует "\n " и не специально проверяет ключ возврата, но я думаю, что это нормально.

обновление

см. ответ ribto ниже, который использует [NSCharacterSet newlineCharacterSet] на месте \n


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

в рамках .H-файл:

UIBarButtonItem* dismissKeyboardButton;

в рамках .файл м:

- (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;
}

попробуйте это :

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    if ([text isEqualToString:@"\n"]) {
        [self.view endEditing:YES];
    }

    return YES;

}

//вы можете использовать это ...

Шаг 1. Первый шаг - убедиться, что вы объявили о поддержке UITextViewDelegate протокол. Это делается в вашем заголовочном файле, например, здесь заголовок называется

EditorController.h:

@interface EditorController : UIViewController  {
  UITextView *messageTextView;
}

@property (nonatomic, retain) UITextView *messageTextView;

@end

Шаг 2. Затем вам нужно будет зарегистрировать контроллер в качестве делегата UITextView. Продолжая из приведенного выше примера, вот как я инициализирую UITextView С EditorController в качестве делегата ...

- (id) init {
    if (self = [super init]) {
        // define the area and location for the UITextView
        CGRect tfFrame = CGRectMake(10, 10, 300, 100);
        messageTextView = [[UITextView alloc] initWithFrame:tfFrame];
        // make sure that it is editable
        messageTextView.editable = YES;

        // add the controller as the delegate
        messageTextView.delegate = self;
    }

Шаг 3. И теперь последняя часть головоломки, чтобы принять меры в ответ на shouldCahngeTextInRange сообщение следующим образом:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range 
  replacementText:(NSString *)text
{
    // Any new character added is passed in as the "text" parameter
    if ([text isEqualToString:@"\n"]) {
        // Be sure to test for equality using the "isEqualToString" message
        [textView resignFirstResponder];

        // Return FALSE so that the final '\n' character doesn't get added
        return FALSE;
    }
    // For any other character return TRUE so that the text gets added to the view
    return TRUE;
}

swift

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

and configure


Код

выполнить UITextViewDelegate в классе / вид вот так:

class MyClass: UITextViewDelegate  { ...

установите делегат textView в self

myTextView.delegate = self

а затем реализовать следующее:

  func textViewDidChange(_ textView: UITextView) {
    if textView.text.characters.count >= 1 {

        if let lastChar = textView.text.characters.last {

            if(lastChar == "\n"){

              textView.text = textView.text.substring(to: textView.text.index(before: textView.text.endIndex))
              textView.resignFirstResponder()
            }
        }
    }
}

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


вы также можете скрыть клавиатуру при касании экрана просмотра:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     UITouch * touch = [touches anyObject];
     if(touch.phase == UITouchPhaseBegan) {
        [txtDetail resignFirstResponder];
      }
 }

быстрым ответом:

override func viewDidLoad() {
    super.viewDidLoad()
    let tapGestureReconizer = UITapGestureRecognizer(target: self, action: "tap:")
    view.addGestureRecognizer(tapGestureReconizer)
}

func tap(sender: UITapGestureRecognizer) {
    view.endEditing(true)
}

я использовал этот код, чтобы изменить ответчика.

 - (BOOL)textView:(UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
    {
        if ([text isEqualToString:@"\n"]) {
            //[textView resignFirstResponder];
            //return YES;
            NSInteger nextTag = textView.tag + 1;
            // Try to find next responder
            UIResponder* nextResponder = [self.view viewWithTag:nextTag];
            if (nextResponder) {
                // Found next responder, so set it.
                [nextResponder becomeFirstResponder];
            } else {
                // Not found, so remove keyboard.
                [textView resignFirstResponder];
            }
            return NO; 


            return NO;
        }
        return YES;

    }

Ok. Все дали ответы с трюками, но я думаю, что правильный способ достичь этого -

подключение после действия на "Кончилось На Выходе" в Interface Builder. (щелкните правой кнопкой мыши TextField и cntrl-перетащите из'кончилось на выходе ' к следующему методу.

-(IBAction)hideTheKeyboard:(id)sender
{
    [self.view endEditing:TRUE];
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range  replacementText:(NSString *)text
{
    if (range.length==0) {
        if ([text isEqualToString:@"\n"]) {
            [txtView resignFirstResponder];
            if(textView.returnKeyType== UIReturnKeyGo){

                [self PreviewLatter];
                return NO;
            }
            return NO;
        }
    }   return YES;
}

+ (void)addDoneButtonToControl:(id)txtFieldOrTextView
{
    if([txtFieldOrTextView isKindOfClass:[UITextField class]])
    {
        txtFieldOrTextView = (UITextField *)txtFieldOrTextView;
    }
    else if([txtFieldOrTextView isKindOfClass:[UITextView class]])
    {
        txtFieldOrTextView = (UITextView *)txtFieldOrTextView;
    }

    UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0,
                                                                          0,
                                                                          [Global returnDeviceWidth],
                                                                          50)];
    numberToolbar.barStyle = UIBarStyleDefault;


    UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"btn_return"]
                                                                style:UIBarButtonItemStyleBordered
                                                               target:txtFieldOrTextView
                                                               action:@selector(resignFirstResponder)];

    numberToolbar.items = [NSArray arrayWithObjects:btnDone,nil];
    [numberToolbar sizeToFit];

    if([txtFieldOrTextView isKindOfClass:[UITextField class]])
    {
         ((UITextField *)txtFieldOrTextView).inputAccessoryView = numberToolbar;
    }
    else if([txtFieldOrTextView isKindOfClass:[UITextView class]])
    {
         ((UITextView *)txtFieldOrTextView).inputAccessoryView = numberToolbar;
    }
}

вопрос спрашивает, как это сделать с помощью клавиши возврата, но я думаю, что это может помочь кому-то с намерением просто заставить клавиатуру исчезнуть при использовании UITextView:

@IBOutlet weak var textView: UITextView!

private func addToolBarForTextView() {
  let textViewToolbar: UIToolbar = UIToolbar()
  textViewToolbar = UIBarStyle.Default
  textViewToolbar = [
    UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Done, target: self, action: #selector(self.cancelInput)),
    UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil),
    UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: #selector(self.doneInput))
  ]
  textViewToolbar()
  self.textView.inputAccessoryView = textViewToolbar //do it for every relevant textView if there are more than one
}

func doneInput() {
  self.textView.resignFirstResponder()
}

func cancelInput() {
  self.textView.text = ""
  self.textView.resignFirstResponder()
}

вызов addToolBarForTextView () на viewDidLoad или какой-то другой метод жизненного цикла.

Кажется, это было идеальное решение для меня.

спасибо,

Мурат


-(BOOL)textFieldShouldReturn:(UITextField *)textField; // called from textfield (keyboard)

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

Я знаю, что это не точный ответ на этот вопрос, но я нашел эту тему после охоты в интернете за ответом. Полагаю, другие разделяют это чувство.

Это моя дисперсия UITapGestureRecognizer, который я нахожу надежным и простым в использовании - просто установите делегат TextView в ViewController.

вместо ViewDidLoad я добавляю UITapGestureRecognizer, когда TextView становится активным для редактирования:

-(void)textViewDidBeginEditing:(UITextView *)textView{
    _tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];

    [self.view addGestureRecognizer: _tapRec];
    NSLog(@"TextView Did begin");
}

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

-(void)tap:(UITapGestureRecognizer *)tapRec{
    [[self view] endEditing: YES];
    [self.view removeGestureRecognizer:tapRec];
    NSLog(@"Tap recognized, tapRec getting removed");
}

надеюсь, это поможет. Это кажется настолько очевидным, но я никогда не видел этого решения нигде в Интернете - я делаю что-то неправильно?


Не забудьте установить делегат для textView-в противном случае resignfirstresponder не будет работать.


попробуйте это .

NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];

Для Xcode 6.4., Swift 1.2. :

   override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent)
    {
        super.touchesBegan(touches, withEvent: event)
        if let touch = touches.first as? UITouch
        {
            self.meaningTextview.resignFirstResponder()
        }
    }

мой хак для этого :

1-Создание кнопки, охватывающей весь вид; 2-отправить его на фоне вашего зрения, 3-измените его тип с "Round Rect" на "Custom" в Инспекторе атрибутов, 4-Создание действия 5 - реализовать метод действий:

- (IBAction)bgTouched:(id)sender 
{
    //to dismiss keyboard on bg btn pressed
    [_userInput resignFirstResponder];
}

где _userInput-ваш выход текстового поля