Как отклонить клавиатуру для UITextView с клавишей возврата?

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

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

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

373
задан GabrieleMartini 17 January 2019 в 13:05
поделиться

33 ответа

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

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

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

342
ответ дан Venk 17 January 2019 в 13:05
поделиться

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

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

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

где _userInput - ваш выход TextField

-1
ответ дан LAOMUSIC ARTS 17 January 2019 в 13:05
поделиться

Функция для скрытия Queboard.

- (void)HideQueyboard
{
    [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder)   to:nil from:nil forEvent:nil];
}
-1
ответ дан Alan10977 17 January 2019 в 13:05
поделиться

Вы должны добавить UIToolbar к верху UITextView, чтобы сделать его проще, чем использовать shouldChangeTextIn

В 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()
}
0
ответ дан Giang 17 January 2019 в 13:05
поделиться
-(BOOL)textFieldShouldReturn:(UITextField *)textField; // called from textfield (keyboard)

-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; // good tester function - thanks
-1
ответ дан SNR 17 January 2019 в 13:05
поделиться

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

NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];
0
ответ дан Hiren Panchal 17 January 2019 в 13:05
поделиться

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

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

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

Мурат

1
ответ дан Murat Yasar 17 January 2019 в 13:05
поделиться

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

Это моя разница с 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");
}

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

0
ответ дан BGC 17 January 2019 в 13:05
поделиться

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

0
ответ дан Ron Holmes 17 January 2019 в 13:05
поделиться

Для Swift 3 этот код позволил мне нажать за пределами UITextView, чтобы закрыть клавиатуру.

@IBOutlet weak var comment: UITextView!

   override func viewDidLoad() {
        super.viewDidLoad()

        comment.delegate = self

        let tapGestureRecogniser = UITapGestureRecognizer(target: self, action: #selector(tap))
        view.addGestureRecognizer(tapGestureRecogniser)
    }

    func tap(sender: UITapGestureRecognizer) {
        if comment.isFirstResponder {
            comment.resignFirstResponder()
        }
    }
-1
ответ дан iCyberPaul 17 January 2019 в 13:05
поделиться

Для 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()
        }
    }
0
ответ дан MB_iOSDeveloper 17 January 2019 в 13:05
поделиться
+ (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;
    }
}
1
ответ дан Venu Gopal Tewari 17 January 2019 в 13:05
поделиться
- (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;
}
1
ответ дан Rinju Jain 17 January 2019 в 13:05
поделиться

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

Соединить следующее действие с событием « Did End On Exit » в Interface Builder. (Щелкните правой кнопкой мыши по TextField и перетащите cntrl из « Закончилось ли при выходе » следующим способом.

-(IBAction)hideTheKeyboard:(id)sender
{
    [self.view endEditing:TRUE];
}
3
ответ дан Mahendra Vishwakarma 17 January 2019 в 13:05
поделиться

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

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

    }
3
ответ дан Avijit Nagare 17 January 2019 в 13:05
поделиться

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

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     UITouch * touch = [touches anyObject];
     if(touch.phase == UITouchPhaseBegan) {
        [txtDetail resignFirstResponder];
      }
 }
3
ответ дан Patrick Hofman 17 January 2019 в 13:05
поделиться

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

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

func tap(sender: UITapGestureRecognizer) {
    view.endEditing(true)
}
3
ответ дан Glauco Neves 17 January 2019 в 13:05
поделиться

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

Шаг 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;
}
4
ответ дан benka 17 January 2019 в 13:05
поделиться

Я решил опубликовать фрагмент прямо здесь:

Убедитесь, что вы заявили о поддержке протокола 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
}
484
ответ дан phatmann 17 January 2019 в 13:05
поделиться

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

- (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
}
74
ответ дан Joseph Francis 17 January 2019 в 13:05
поделиться

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

Я нашел ответы 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;
}
42
ответ дан Community 17 January 2019 в 13:05
поделиться

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

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

РЕДАКТИРОВАТЬ: Я также хотел бы добавить, что если вы используете 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];
}

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

35
ответ дан TMilligan 17 January 2019 в 13:05
поделиться

Swift Code

Реализовать UITextViewDelegate в вашем классе / Просмотреть так:

class MyClass: UITextViewDelegate  { ...

установить делегата textView на себя

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

РЕДАКТИРОВАТЬ Я обновил код, потому что это никогда не хорошая идея, чтобы изменить пользовательский ввод в текстовое поле для обходного пути и не сбрасывать состояние после завершения кода взлома .

4
ответ дан Joyful Machines 17 January 2019 в 13:05
поделиться

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

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()
        }
    }
}
32
ответ дан swiftBoy 17 January 2019 в 13:05
поделиться

Существует другое решение при использовании с 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];
}
16
ответ дан swiftBoy 17 January 2019 в 13:05
поделиться
-(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"]), вы не можете редактировать

26
ответ дан David 17 January 2019 в 13:05
поделиться

Свифт

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

and configure

6
ответ дан Eduardo Oliveros Acosta 17 January 2019 в 13:05
поделиться

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

в файле .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;
}
6
ответ дан David 17 January 2019 в 13:05
поделиться

Так же, как матовый комментарий к 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];
}
5
ответ дан friend 17 January 2019 в 13:05
поделиться

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

ОБНОВЛЕНИЕ

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

5
ответ дан ToddB 17 January 2019 в 13:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: