Como dispensar o teclado para o UITextView com a tecla de retorno?

Na biblioteca do IB, a introdução nos diz que quando a tecla de retorno é pressionada, o teclado do UITextView irá desaparecer. Mas, na verdade, a chave de retorno só pode agir como ‘\ n’.

Eu posso adicionar um botão e usar [txtView resignFirstResponder] para ocultar o teclado.

Mas existe uma maneira de adicionar a ação para a chave de retorno no teclado para que eu não precise adicionar o UIButton ?

    UITextView não possui nenhum método que será chamado quando o usuário pressionar a tecla de retorno. Se você quiser que o usuário possa adicionar apenas uma linha de texto, use um UITextField . Acertar o retorno e ocultar o teclado para um UITextView não segue as diretrizes da interface.

    Mesmo assim, se você quiser fazer isso, implemente o textView:shouldChangeTextInRange:replacementText: de UITextViewDelegate e, se a substituição do texto for \n , oculte o teclado.

    Pode haver outras formas, mas não tenho conhecimento de nenhuma.

    Imaginei que eu postaria o trecho aqui mesmo:

    Certifique-se de declarar suporte para o protocolo UITextViewDelegate .

     - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if([text isEqualToString:@"\n"]) { [textView resignFirstResponder]; return NO; } return YES; } 

    Atualização do Swift 4.0:

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

    Eu sei que isso já foi respondido, mas eu realmente não gosto de usar a string literal para a nova linha, então aqui está o que eu fiz.

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

    Atualização do 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 } 

    Eu sei que isso foi respondido muitas vezes, mas aqui estão meus dois centavos para a questão.

    Eu encontrei as respostas por samvermette e ribeto realmente úteis, e também o comentário de maxpower na resposta do ribeto . Mas há um problema com essas abordagens. O problema que Matt menciona na resposta do samvermette e é que, se o usuário quiser colar algo com uma quebra de linha dentro dele, o teclado se esconderia sem colar nada.

    Então, minha abordagem é uma mistura das três soluções mencionadas acima e apenas verificando se a string digitada é uma nova linha quando o comprimento da string é 1, então nos certificamos de que o usuário esteja digitando ao invés de colar.

    Aqui está o que eu fiz:

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

    Uma maneira mais elegante é dispensar o teclado quando o usuário toca em algum lugar fora do quadro do teclado.

    Primeiro, defina a visualização do seu ViewController para a class “UIControl” no inspetor de identidade no UIBuilder. Controle e arraste a visualização para o arquivo de header do ViewController e associe-a como uma ação com o evento como Retoque Interno, como:

    ViewController.h

     -(IBAction)dismissKeyboardOnTap:(id)sender; 

    No arquivo principal do ViewController, ViewController.m:

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

    Você pode exigir um toque duplo ou um toque longo usando técnicas semelhantes. Você pode precisar configurar seu ViewController para ser um UITextViewDelegate e conectar o TextView ao ViewController. Esse método funciona para o UITextView e o UITextField.

    Fonte: Big Nerd Ranch

    EDIT: Eu também gostaria de acrescentar que se você estiver usando um UIScrollView, a técnica acima pode não funcionar tão facilmente através do construtor de interface. Nesse caso, você poderia usar um UIGestureRecognizer e chamar o método [[auto view] endEditing: YES] dentro dele. Um exemplo seria:

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

    Quando o usuário toca fora do teclado e não toca em um espaço de input, o teclado irá ignorar.

    Adicione este método no seu controlador de exibição.

    Swift :

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

    Este método também pode ser útil para você:

     /** 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; 

    Adicione também UITextViewDelegate

    Não esqueça de confirmar o protocolo

    Se você não adicionou if([text isEqualToString:@"\n"]) você não pode editar

    Há outra solução ao usar com o uitextview, Você pode adicionar a barra de ferramentas como InputAccessoryView em “textViewShouldBeginEditing” e, a partir deste botão da barra de ferramentas, você pode dispensar o teclado, o código para isso é o seguinte:

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

    No método textviewdelegate

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

    Na ação de Button Done que está na barra de ferramentas está seguindo:

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

    Eu encontrei a resposta de josebama para ser a resposta mais completa e limpa disponível neste tópico.

    Abaixo está a syntax do Swift 3 para isso:

     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 } 

    Assim como o comentário mate para samvermette, também não gosto da idéia de detectar “\ n”. A chave “return” está lá por um motivo no UITextView, que é ir para a próxima linha do curso.

    A melhor solução na minha opinião é imitar o aplicativo de mensagens do iPhone – que é adicionar barra de ferramentas (e botão) no teclado.

    Eu tenho o código do seguinte post:

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

    Passos:

    -Adicione a barra de ferramentas ao seu arquivo XIB – defina a altura como 460

    -Adicionar item do botão da barra de ferramentas (se ainda não tiver sido adicionado). Se você precisar alinhar à direita, adicione também item de botão de barra flexível ao XIB e mova o item de botão da barra de ferramentas

    -Crie ação que vincule seu item de botão a resignFirstResponder da seguinte forma:

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

    -Então:

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

    Apenas resolvi este problema de uma maneira diferente.

    • Crie um botão que será colocado em segundo plano
    • No Inspetor de Atributos, altere o tipo de botão para personalizado e o botão fica transparente.
    • Expanda o botão para cobrir toda a visão e verifique se o botão está atrás de todo o outro object. Uma maneira fácil de fazer isso é arrastar o botão para o topo da lista no View
    • Controle arraste o botão para o arquivo viewController.h e crie uma ação (Evento enviado: Retocar interior) como:

       (IBAction)ExitKeyboard:(id)sender; 
    • Em ViewController.m deve ser parecido com:

       (IBAction)ExitKeyboard:(id)sender { [self.view endEditing:TRUE]; } 
    • Execute o aplicativo e, quando você clicar fora do TextView, o teclado desaparecerá

    Adicionar um observador em viewDidLoad

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

    e use o seletor para verificar “\ n”

     -(void) textViewKeyPressed: (NSNotification*) notification { if ([[[notification object] text] hasSuffix:@"\n"]) { [[notification object] resignFirstResponder]; } } 

    Ele usa “\ n” e não verifica especificamente se há uma chave de retorno, mas acho que está tudo bem.

    ATUALIZAR

    Veja a resposta de ribto abaixo que usa [NSCharacterSet newlineCharacterSet] no lugar de \n

    Usando o controlador de navegação para hospedar uma barra para dispensar o teclado:

    no arquivo .h:

     UIBarButtonItem* dismissKeyboardButton; 

    no arquivo .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; } 

    Tente isto:

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

    // Você pode usar isso …

    Etapa 1. O primeiro passo é certificar-se de declarar suporte para o protocolo UITextViewDelegate . Isso é feito no seu arquivo de header, como exemplo, aqui é o header chamado

    EditorController.h:

     @interface EditorController : UIViewController { UITextView *messageTextView; } @property (nonatomic, retain) UITextView *messageTextView; @end 

    Etapa 2. Em seguida, você precisará registrar o controlador como o delegado do UITextView. Continuando com o exemplo acima, aqui está como inicializei o UITextView com o EditorController como…

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

    Passo 3. E agora a última peça do quebra-cabeça é agir em resposta à mensagem shouldCahngeTextInRange seguinte forma:

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

    rápido

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

    e configure

    Código Swift

    Implemente UITextViewDelegate em sua class / View da seguinte forma:

     class MyClass: UITextViewDelegate { ... 

    definir o delegado textView para auto

     myTextView.delegate = self 

    Em seguida, implemente o seguinte:

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

    EDIT Eu atualizei o código porque nunca é uma boa idéia para alterar a input do usuário em um campo de texto para um workarround e não redefinir o estado após o código de hack completo.

    Você também pode ocultar o teclado ao tocar na canvas de exibição:

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

    Resposta rápida:

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

    Eu usei esse código para alterar o respondedor.

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

    Está bem. Todo mundo deu respostas com truques, mas eu acho que o caminho certo para conseguir isso é por

    Conectando a seguinte ação ao evento ” Did End On Exit ” no Interface Builder . (clique com o botão direito do mouse no TextField e pressione TextField e arrastar de ‘ Did end on exit ‘ para o seguinte método.

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

    A questão pergunta como fazê-lo com a chave de retorno, mas acho que isso poderia ajudar alguém com a intenção de apenas fazer desaparecer o teclado ao usar o 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() } 

    Chame addToolBarForTextView () no viewDidLoad ou outro método de ciclo de vida.

    Parece que foi a solução perfeita para mim.

    Felicidades,

    Murat

     -(BOOL)textFieldShouldReturn:(UITextField *)textField; // called from textfield (keyboard) -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; // good tester function - thanks 

    Eu sei que não é a resposta exata para esta pergunta, mas eu encontrei este segmento depois de caçar a internet para baixo para uma resposta. Eu suponho que os outros compartilham esse sentimento.

    Esta é a minha variância do UITapGestureRecognizer que eu acho confiável e fácil de usar – basta definir o delegado do TextView para o ViewController.

    Em vez de ViewDidLoad, adiciono o UITapGestureRecognizer quando o TextView se torna ativo para edição:

     -(void)textViewDidBeginEditing:(UITextView *)textView{ _tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)]; [self.view addGestureRecognizer: _tapRec]; NSLog(@"TextView Did begin"); } 

    Quando eu bato fora do TextView, a exibição termina no modo de edição e o UITapGestureRecognizer é removido para que eu possa continuar interagindo com outros controles na exibição.

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

    Eu espero que isso ajude. Parece tão óbvio, mas eu nunca vi essa solução em qualquer lugar na web – estou fazendo algo errado?

    Não se esqueça de definir o delegado para o textView – caso contrário, resignfiresponder não funcionará.

    Tente isso.

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

    Para o Xcode 6.4., Swift 1.2. :

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

    Meu hack para isso:

    1- criar um botão cobrindo toda a visão; 2- enviá-lo para o fundo de sua visão, 3- alterá-lo. Digite de “Round Rect” para “Custom” no Attribute Inspector, 4- crie uma ação 5- implemente o método de ação:

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

    onde _userInput é sua saída TextField