Como descartar o teclado do UITextView com a tecla Enter?


382

Na biblioteca do IB, a introdução nos diz que, quando a returntecla é pressionada, o teclado UITextViewdesaparece. Mas, na verdade, a returnchave só pode atuar como '\ n'.

Posso adicionar um botão e usá-lo [txtView resignFirstResponder]para ocultar o teclado.

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


Siga as instruções nesta postagem do blog: iphonedevelopertips.com/cocoa/…
ManojN

Respostas:


354

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

Mesmo assim, se você quiser fazer isso, implemente o textView:shouldChangeTextInRange:replacementText:método UITextViewDelegatee, nessa verificação, se o texto de substituição é \n, oculte o teclado.

Pode haver outras maneiras, mas não conheço nenhuma.


11
Obrigado e o método funciona bem. O motivo para usar o UITextView é que ele pode conter texto em várias linhas. E agora estou usando-o como uma caixa de mensagem.
2200 Chilly Zhong

28
É bastante fácil alterar a chave de retorno para "concluído" usando o [textField setReturnKeyType: UIReturnKeyDone];construtor de interfaces ou usando-o
Casebash

9
Ok, agora eu entendo que a maneira como a Apple de terminar com um campo de texto multilinha é adicionar feito para a barra de menus
Casebash

8
Esta não é uma boa maneira de resolver isso, porque você está restringindo o usuário a usar enter para sair do teclado. Provavelmente, a melhor maneira é adicionar um botão que execute o método resignFirstResponder.
He

5
@Casebash. Parece que definir a chave de retorno como "concluído" não resolve o problema no Xcode 6.4, Swift 2.0. Defino a chave usando o IB.
MB_iOSDeveloper

505

Imaginei que eu postaria o trecho aqui:

Certifique-se de declarar suporte ao UITextViewDelegateprotocolo.

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

75
O problema é que essa não é realmente uma maneira de detectar que o usuário tocou na tecla de retorno . O usuário pode colar um caractere de retorno no campo de texto e você receberá a mesma mensagem delegada. Basicamente, você está usando incorretamente a exibição de texto. A maneira de descartar o teclado é (1) não fazê-lo (como ao escrever uma mensagem no aplicativo Mail) ou (2) ter um botão Concluído em outro local da interface (como no aplicativo Notes). Você pode anexar um botão como uma visualização acessória ao teclado, por exemplo.
matt

@ Sam V esse trecho era cara legal. funciona para mim. graças a um homem de tonelada. Existe algum trecho para dissimulação do teclado numérico. Atenciosamente shishir
Shishir.bobby

Magnífico. Apenas um lembrete de que, em algumas situações, para se livrar do teclado, tente ao longo das linhas ... [self.view endEditing: YES];
Fattie

@ Vojto, funciona bem no iPad. Você provavelmente não definiu o delegado.
Vincent

4
O problema é que o teclado pode estar ocultando parte da interface usada para descartar. É realmente absurdo que o IOS não tenha um botão em cada teclado dedicado a descartá-lo, para que o usuário possa fazê-lo, se desejar.
Sani Elfishawy

80

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
}

6
Eu posso modificá-lo assim: NSRange resultRange = [text rangeOfCharacterFromSet: [NSCharacterSet newlineCharacterSet] opções: NSBackwardsSearch]; Como isso é um hack de qualquer maneira, parece que verificar se o retorno da sequência de caracteres pode ser uma rota mais segura.
Maxpower

@maxpower Muito bom comentário. Além disso, é melhor verificar o texto substituído, por exemplo NSString *replacedText = [textView.text stringByReplacingCharactersInRange:range withString:text].
Rudolf Adamkovič

Imagine um usuário colando algum texto copiado de outro lugar que contenha uma nova linha. Eles provavelmente ficariam confusos quando, em vez de anexar o texto, o aplicativo apenas descartasse o teclado.
Nikolai Ruhe

44

Sei que isso já foi respondido várias vezes, mas aqui estão meus dois centavos para o problema.

Eu achei as respostas de 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 é que, se o usuário quiser colar algo com uma quebra de linha, o teclado se esconderá sem colar nada.

Portanto, minha abordagem é uma mistura das três soluções mencionadas acima e apenas verificamos se a string inserida é uma nova linha quando o comprimento da string é 1, para garantir que o usuário esteja digitando em vez 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;
}

Esta é a melhor solução para esse problema. A resposta samvermette não considera a situação em que o usuário deseja colar um texto.
Marcopivaf

36

Uma maneira mais elegante é descartar 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 classe "UIControl" no inspetor de identidade do UIBuilder. Arraste a vista para o arquivo de cabeçalho do ViewController com a tecla Control pressionada e vincule-a como uma ação ao 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 toque longo usando técnicas semelhantes. Pode ser necessário definir seu ViewController como UITextViewDelegate e conectar o TextView ao ViewController. Este método funciona para UITextView e 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 Interface Builder. Nesse caso, você pode usar um UIGestureRecognizer e chamar o método [[self 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 entrada, o teclado será descartado.


11
Eu gosto da ideia, GestureRecognizermas com um grande problema é que todos os botões ou controles na exibição não são mais clicáveis.
expert

35

Adicione este método ao 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()
        }
    }
}

2
Não se esqueça de protocolo confirmam UITextViewDelegate :)
swiftBoy

Não acho que seja uma boa ideia substituir o touchesBegan e não ligar super.touchesBegan(touches:withEvent:).
TGO 15/05

Para expressar a natureza simétrica desse código, você deve escrever else { return true }.
significado-importa

@ significado não importa de todo
Alexander Volkov

@AlexanderVolkov Você não concorda que é uma situação simétrica, você não sabe o que quero dizer, você não acredita no valor do código semanticamente correto ou ...?
significado-importa

26
-(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 se esqueça de confirmar o protocolo

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


2
-1 Esta é apenas uma versão mais pobre da resposta de samvermette. Você perdeu o retorno NOse o texto for igual a @"\n".
devios1

17

Há outra solução ao usar o uitextview. Você pode adicionar a barra de ferramentas como InputAccessoryView em "textViewShouldBeginEditing" e, no botão pronto desta barra de ferramentas, você pode descartar o teclado, o código a seguir é 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 do botão Concluído, que está na barra de ferramentas, é o seguinte:

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

17

Achei a resposta de josebama a resposta mais completa e limpa disponível neste tópico.

Abaixo está a sintaxe do 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
}

O resultRangeobjetivo é testar se o texto contém apenas linhas novas que evitam "\ n" código rígido.
Qinghua

6

rápido

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

e configurar


De onde é essa captura de tela?
Sam

6

Usando o controlador de navegação para hospedar uma barra para descartar 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;
}

5

Assim como comentários matt para samvermette, também não gosto da idéia de detectar "\ n". A tecla "return" existe 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 a barra de ferramentas (e o botão) ao teclado.

Eu recebi o código da seguinte postagem no blog:

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

Passos:

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

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

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

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

Fora do assunto. Embora sua solução seja elegante, ela não responde à pergunta original: "Como descartar o teclado do UITextView com a tecla Enter?". Há situações em que o UITextView é empregado para simular um UITextField de quebra de linha, não para inserir várias linhas.
21440 SwiftArchitect

2
Embora esteja fora do tópico, é muito útil. Também quero que um UITextView seja inserido com várias linhas e descartar o teclado quando desejar.
Yeung

5

Apenas resolvi esse 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 isso torna o botão transparente.
  • Expanda o botão para cobrir toda a exibição e verifique se o botão está atrás de todos os outros objetos. A maneira mais fácil de fazer isso é arrastar o botão para o topo da exibição de lista na tela Exibir.
  • Controle arraste o botão para o viewController.harquivo e crie uma ação (Evento enviado: Retoque interno) como:

    (IBAction)ExitKeyboard:(id)sender;
  • Em ViewController.mdeve se parecer com:

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

Você também deve adicionar: - (void) textViewDidEndEditing: (UITextView *) textView {[self.TextView resignFirstResponder]; }
samouray 15/07/2015

5

Adicionar um observador no 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á OK.

ATUALIZAR

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


Errar, ele usa \ne a chave de retorno é detectada com base em, \nportanto, verifica a chave de retorno. A única diferença é que você está usando notificações em vez de usar o textViewDelegates.
precisa saber é o seguinte

Agora, acho [NSCharacterSet newlineCharacterSet]que procurar e não \ n pode ser o melhor caminho a percorrer.
ToddB

5

Código Swift

Implemente UITextViewDelegate em sua classe / View da seguinte forma:

class MyClass: UITextViewDelegate  { ...

defina o delegado textView como auto

myTextView.delegate = self

E, 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 Atualizei o código porque nunca é uma boa ideia alterar a entrada do usuário em um campo de texto para uma solução alternativa e não redefinir o estado após a conclusão do código de hack.


4

Tente o seguinte:

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

    return YES;

}

4

// Você pode usar isso ...

Etapa 1. A primeira etapa é certificar-se de que você declara suporte ao UITextViewDelegateprotocolo. Isso é feito no seu arquivo de cabeçalho, como exemplo, aqui está o cabeçalho 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 representante do UITextView. Continuando com o exemplo acima, aqui está como eu inicializei o UITextViewcom EditorControllercomo delegado…

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

Etapa 3. E agora a peça final do quebra-cabeça é agir em resposta à shouldCahngeTextInRangemensagem da seguinte maneira:

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

3

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

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

IMHO, esta é uma abordagem muito boa, muito melhor do que com o botão que cobre toda a exibição.
WebOrCode

3

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

3

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;

    }

por que não usar [self.view endEditing: YES]; uma vez??
ajay_nasa

3

A pergunta pergunta como fazê-lo com a tecla Enter, mas acho que isso poderia ajudar alguém com a intenção de simplesmente fazer o teclado desaparecer ao usar o UITextView:

private func addToolBarForTextView() {
    let textViewToolbar: UIToolbar = UIToolbar()
    textViewToolbar.barStyle = .default
    textViewToolbar.items = [
        UIBarButtonItem(title: "Cancel", style: .done,
                  target: self, action: #selector(cancelInput)),
        UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
                  target: self, action: nil),
        UIBarButtonItem(title: "Post Reply", style: .done,
                  target: self, action: #selector(doneInput))
    ]
    textViewToolbar.sizeToFit()
    yourTextView.inputAccessoryView = textViewToolbar
}

@objc func cancelInput() { print("cancel") }
@objc func doneInput() { print("done") }

override func viewDidLoad() {
    super.viewDidLoad()
    addToolBarForTextView()
}

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

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

Felicidades,

Murat


11
Para 2019, agora copie e cole, sem erros de sintaxe e nomes atuais
Fattie 23/11/19

11
de longe a melhor resposta aqui. Eu apenas corrigi o erro simples de sintaxe, é claro, edite como desejar. Obrigado!
Fattie 23/11/19

2

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

Conectando a seguinte ação ao evento " Terminou na saída " em Interface Builder. (clique com o botão direito do mouse TextFielde arraste com a tecla Ctrl pressionada de ' Terminou ao sair ' para o seguinte método.

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

6
-1 A pergunta é sobre UITextView e não UITextField meu amigo
Yogi

2
a maioria dessas respostas está aqui com votos, pois combina com vários cenários de diferentes desenvolvedores.
carbonr

Se você estiver usando um UITextField, esta é a maneira de fazê-lo. BTW, você deve usar SIM / NÃO para BOOLs do Objective-C, não VERDADEIRO / FALSO.
Jon Shier

11
@jshier: TRUE / FALSE é OK também
Yogi

2

Semelhante a outras respostas usando a UITextViewDelegateinterface rápida, mas mais recente, isNewlineseria:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if let character = text.first, character.isNewline {
        textView.resignFirstResponder()
        return false
    }
    return true
}

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

0

Eu sei que não é a resposta exata para essa pergunta, mas encontrei esse tópico depois de procurar na Internet uma resposta. Suponho que outros compartilhem esse sentimento.

Essa é a minha variação do UITapGestureRecognizer que considero confiável e fácil de usar - basta definir o delegado do TextView como 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 toco fora do TextView, a exibição termina o modo de edição e o UITapGestureRecognizer se remove 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 nunca vi essa solução em nenhum lugar da Web - estou fazendo algo errado?


0

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


0

Tente isso.

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

0

Para o 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

Você deve adicionar UIToolbarao topo o UITextView para facilitar, em vez de usarshouldChangeTextIn

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

De longe a melhor solução. Observe que, em vez de definir o quadro, basta usartoolbar.sizeToFit()
Fattie 23/11/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.