Как убрать клавиатуру для UITextView с ключом возврата?

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

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

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

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

Я нашел ответы 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;
}

Ответ 5

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

Сначала установите представление 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.

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

EDIT: Я также хотел бы добавить, что если вы используете 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];
}

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

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

Ниже приведен синтаксис 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
}

Ответ 10

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

в .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;
}

Ответ 11

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

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

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

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

Шаги:

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

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

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

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

-Тогда:

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

Ответ 12

Добавить наблюдателя в 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" и специально не проверяет ключ возврата, но я думаю, что все в порядке.

UPDATE

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

Ответ 13

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

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

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

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

Ответ 14

Попробуйте следующее:

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

    return YES;

}

Ответ 15

Swift Code

Реализовать 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()
            }
        }
    }
}

ИЗМЕНИТЬ Я обновил код, потому что никогда не рекомендуется менять ввод пользователя в текстовое поле для рабочего стола и не восстанавливать состояние после завершения кода взлома.

Ответ 16

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

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

EditorController.h:

@interface EditorController : UIViewController  {
  UITextView *messageTextView;
}

@property (nonatomic, retain) UITextView *messageTextView;

@end

Шаг 2. Затем вам нужно будет зарегистрировать контроллер как делегат UITextViews. Продолжая из приведенного выше примера, вот как я инициализировал 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;
}

Ответ 17

быстры

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

и настроить

Ответ 18

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

Подключение следующего действия к событию Завершить выходInterface Builder. (щелкните правой кнопкой мыши по элементу TextField и cntrl-drag от << → до конца до следующего метода.

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

Ответ 19

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

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

Ответ 20

Быстрый ответ:

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

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

Ответ 21

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

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

    }

Ответ 22

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

Ответ 23

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

Ответ 24

Вопрос задает вопрос, как это сделать с помощью ключа возврата, но я думаю, что это может помочь кому-то с намерением просто отключить клавиатуру при использовании 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 или какой-либо другой метод жизненного цикла.

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

Приветствия,

Мурат

Ответ 25

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

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

Ответ 26

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

Это моя дисперсия 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");
}

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

Ответ 27

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

Ответ 28

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

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

Ответ 29

Для 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()
        }
    }

Ответ 30

Мой взломать для этого:

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

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

где _userInput - это ваша текстовая панель