Como você dispensa o teclado ao editar um UITextField

181

Sei que preciso solicitar ao meu UITextField que renuncie ao primeiro atendedor quando quiser desligar o teclado, mas não sei como saber quando o usuário pressionou a tecla "Concluído" no teclado. Existe uma notificação que eu possa assistir?

kubi
fonte
2
[self.view endEditing: YES]; em começou toques delegado é a melhor solução
Zar E Ahmer

Respostas:

351

Eu coloquei o delegado da na UITextFieldminha ViewControllerclasse.

Nessa classe, implementei esse método da seguinte maneira:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return NO;
}
kubi
fonte
Veja o exemplo acima ... conecte que usar o IntefaceBuilder à ação em qualquer coisa que você esteja usando como controlador ... sempre que o usuário rejeitar o sistema de entrada de texto (pressionadas), isso será chamado ...
Jason Coco
2
Qualquer um deles funcionará - o campo de texto envia sua ação quando o usuário pressiona a tecla Return ("Concluído", qualquer que seja)) e também envia seu delegado -textFieldShouldReturn :.
Noah Witherspoon
BTW - isso também funciona para um UISearchBar. Por exemplo, meu código tinha um membro IBOutlet searchBarTusb; Quando minha 'chave de retorno' (UIReturnKeySearch) foi clicada, - (void) searchBarSearchButtonClicked :, eu coloquei a instrução [searchBarTusb resignFirstResponder]; Observe também que a 'chave de retorno' foi definida no NIB usando o Interface Builder.
mobibob
Por que retornar em NOvez de YES?
Iulian Onofrei 30/01/19
@IulianOnofrei O comportamento padrão do botão de retorno é adicionar um retorno de linha e manter o teclado na tela. Ao retornar, NOvocê evita adicionar um retorno de linha ao texto.
Kubi
47

Se você conectar o evento DidEndOnExit do campo de texto a uma ação (IBAction) no InterfaceBuilder, ele receberá uma mensagem quando o usuário dispensar o teclado (com a tecla Enter) e o remetente será uma referência ao UITextField que acionou o evento.

Por exemplo:

-(IBAction)userDoneEnteringText:(id)sender
{
    UITextField theField = (UITextField*)sender;
    // do whatever you want with this text field
}

Em seguida, no InterfaceBuilder, vincule o evento DidEndOnExit do campo de texto a esta ação no seu controlador (ou o que você estiver usando para vincular eventos da interface do usuário). Sempre que o usuário digitar texto e dispensar o campo de texto, o controlador receberá esta mensagem.

Jason Coco
fonte
O único evento que parece funcionar pode ser textFieldDidEndEditing, que informa que ele é enviado somente após o UITextField renunciar ao status de primeiro respondedor. Como sei quando preciso renunciar ao status de socorrista?
kubi
Sinto muito sobre a terminologia ... não é uma notificação real (evento) ... eu vou editar a minha resposta com um exemplo rápido e explicações, assim que ver que :)
Jason Coco
1
Para esclarecer esta resposta, o textField envia o evento "Terminou na saída" quando você pressiona a tecla de retorno, então é esse que você precisa vincular ao seu controlador. Eu acho que esse método é mais fácil do que o descrito acima.
Kubi 22/04/09
2
você pode editar esta resposta para mencionar qual evento será transmitido, por favor? Isso é obviamente melhor do que definir o delegado.
Dan Rosenstark
1
Deseja votar novamente esta resposta, mas não pode até mencionar o evento DidEndOnExit. Alguém com privilégios de edição, faça a alteração se o OP não for?
James Hart
32

Você também pode criar um método no seu controlador

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

e, em seguida, no Connection Inspector no IB, conecte o evento "Terminou na saída" a ele.

Hugo
fonte
1
Isso está quase incorreto ou, pelo menos, está errado. Ao se inscrever no DidEndOnExitevento, você não precisa ligar resignFirstResponder. Você pode testar isso colocando um ponto de interrupção simbólico [UIResponder resignFirstResponder]. Observe que, mesmo se você não chamar resignFirstResponder, ele ainda será chamado pelo sistema. Isso é explicado pelos excelentes livros de Matt Neuburg: apeth.com/iOSBook/…
Chris Conover
19

kubi, obrigado. Seu código funcionou. Só para ser explícito (para iniciantes gosta) como você diz que você tem que definir o UITextField's delegatepara ser igual ao ViewController em que reside o campo de texto. Você pode fazer isso onde quiser. Eu escolhi o viewDidLoadmétodo

- (void)viewDidLoad 
{
    // sets the textField delegates to equal this viewController ... this allows for the keyboard to disappear after pressing done
    daTextField.delegate = self;
}
Roubar
fonte
Se você adicionou um campo de texto ao seu storyboard ou NIB, também pode definir o campo de texto delegate. Você não precisa fazer isso programaticamente, conforme demonstrado acima. Qualquer abordagem funciona bem.
Rob
18

Aqui está um truque para obter o comportamento automático de dispensa de teclado sem nenhum código. Na ponta, edite o objeto proxy do Primeiro Respondente no Inspetor de Identidade, adicionando uma nova ação do Primeiro Respondente; vamos chamá-lo dummy:. Agora conecte o evento Terminou na saída do campo de texto à dummy:ação do objeto proxy do Primeiro Respondente. É isso aí! Como o evento Terminou na saída do campo de texto agora tem um par de ação-destino, o campo de texto automaticamente dispensa o teclado quando o usuário toca em Retornar; e como não há penalidade por não encontrar um manipulador para uma mensagem enviada na cadeia de respostas, o aplicativo não falha, mesmo que não haja implementação em dummy:nenhum lugar.

mate
fonte
@matt Descobri que, se eu adicionar um desenrolar segue E conectar o evento didEndOnExit ENTÃO, o desenrolar segue será acionado ao pressionar Return. Sem a conexão do evento, o segue não é acionado. Ótimo, mas não é? Alguma observação? BTW: Eu tenho seus livros Swift (terminado) e iOS10 (no cap. 6). Eles me ajudaram tremendamente!
Verticon
@Verticon a pergunta e resposta não tem nada a ver com segues, então eu não entendo a questão ... :( isto é puramente sobre demissão teclado
mate
@matt Desculpe, cara. Eu estava com o piggy backing porque 1) descobri esse segmento enquanto estava lidando com como lidar com a chave de retorno do UITextField; e 2) foi uma chance de interagir com você (thx para os livros da). Não há "problema". Apenas falta de entendimento da minha parte sobre por que / como funciona da maneira que funciona.
Verticon
@Verticon Peço desculpas por não poder ajudar. Sinta-se à vontade para formular uma nova pergunta com mais informações (projeto de demonstração?) E me mande uma mensagem, se puder ser útil.
Matt
11

Basta adicionar

[textField endEditing:YES];

onde você deseja desativar o teclado e exibir a exibição do seletor.

user415897
fonte
10

No Swift, você pode escrever uma IBAction no Controller e definir o evento Did End On Exit do campo de texto para essa ação

@IBAction func returnPressed(sender: UITextField) {
    self.view.endEditing(true)
}
Safin Ahmed
fonte
5

Swift 4.2 e funcionará 100%

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        self.textField.delegate = self

    }

    // hide key board when the user touches outside keyboard

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

    // user presses return key

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}
Gulsan Borbhuiya
fonte
4

Você também pode usar

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
  {

   [self.yourTextField resignFirstResponder];

  }

Melhor se você tiver muitos Uitextfields:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 {    
     [self.view endEditing:YES];
 }
Metalhead1247
fonte
2

Aqui está o que eu fiz para fazê-lo funcionar, e acho que é necessário para qualquer pessoa com um teclado numérico (ou qualquer outro sem botão pronto):

  1. Mudei o UIView no ViewController para um UIControl.
  2. Eu criei uma função chamada

    -(IBAction)backgroundIsTapped:(id)sender

Isso também foi definido no arquivo .h.

Depois disso, vinculei ao bit 'touch down' do ViewController no Interface Builder.

Na função 'background is tapped', coloquei o seguinte:

    [answerField resignFirstResponder];

Lembre-se de alterar 'answerField' para o nome do UITextField do qual você deseja remover o teclado (obviamente, verifique se o seu UITextField está definido como abaixo :)

    IBOutlet UITextField * <nameoftextfieldhere>;

Eu sei que esse tópico provavelmente morreu há muito tempo ... mas espero que isso ajude alguém, em algum lugar!

Ryan Bourne
fonte
..mas não funciona tão bem se o usuário tocar em outro controle.
Ragnarius 31/07
2

Você notará que o método "textFieldShouldReturn" fornece o objeto de campo de texto que pressionou a tecla DONE. Se você definir o TAG, poderá ativar esse campo de texto. Ou você pode acompanhar e comparar o ponteiro do objeto com algum valor de membro armazenado por seu criador.

Minha abordagem é assim para um auto-estudo:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    bool fDidResign = [textField resignFirstResponder];

    NSLog(@"%s: did %resign the keyboard", __FUNCTION__, fDidResign ? @"" : @"not ");

    return fDidResign;
}

Enquanto isso, coloquei o teste de "validação" que nega a renúncia. É apenas para ilustração, portanto, se o usuário digitar NÃO! no campo, não será descartado. O comportamento era como eu queria, mas a sequência de saída não era como eu esperava.

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    if( [[textField text] isEqualToString:@"NO!"] ) {
        NSLog(@"%@", textField.text);
        return NO;
    } else {
        return YES;
    }
}

A seguir, minha saída do NSLog para essa negação, seguida pela aceitação. Você notará que estou retornando o resultado da demissão, mas eu esperava que ela retornasse FALSE para que eu denunciasse o chamador ?! Fora isso, ele tem o comportamento necessário.

13.313 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
13.320 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
13.327 StudyKbd [109: 207] NÃO!
13.333 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: renunciou ao teclado
59.891 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
59.897 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
59.917 StudyKbd [109: 207] - [StudyKbdViewController doneEditText]: NÃO
59.928 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: renunciou ao teclado
mobibob
fonte
1
u pode explicar ..se eu voltar NAO ou SIM em ambos os casos mesmas coisas acontecem de modo que a necessidade de voltar sim no método delegado textFieldShouldReturn
K. Jaiswal
1

Aqui está uma maneira bastante clara de finalizar a edição com a tecla Return ou com um toque em segundo plano.

No construtor Interface, incorpore seus campos em uma exibição da classe UIFormView

O que essa classe:

  • Anexar-se automaticamente como delegado de campos (despertado da ponta ou adicionado manualmente)
  • Mantenha uma referência no campo editado atual
  • Ignore o teclado ao retornar ou toque em segundo plano

Aqui está o código:

Interface

#import <UIKit/UIKit.h>

@interface UIFormView : UIView<UITextFieldDelegate>

-(BOOL)textFieldValueIsValid:(UITextField*)textField;
-(void)endEdit;

@end

Implementação

#import "UIFormView.h"

@implementation UIFormView
{
    UITextField* currentEditingTextField;
}

// Automatically register fields

-(void)addSubview:(UIView *)view
{
    [super addSubview:view];
    if ([view isKindOfClass:[UITextField class]]) {
        if ( ![(UITextField*)view delegate] ) [(UITextField*)view setDelegate:self];
    }
}

// UITextField Protocol

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    currentEditingTextField = textField;
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    currentEditingTextField = NULL;
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self endEdit];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if ([self textFieldValueIsValid:textField]) {
        [self endEdit];
        return YES;
    } else {
        return NO;
    }
}

// Own functions

-(void)endEdit
{
    if (currentEditingTextField) {
        [currentEditingTextField endEditing:YES];
        currentEditingTextField = NULL;
    }
}


// Override this in your subclass to handle eventual values that may prevent validation.

-(BOOL)textFieldValueIsValid:(UITextField*)textField
{
    return YES;
}

@end
  • Subclassificando o formulário e substituindo o textFieldValueIsValid:método, você pode evitar o final da edição se o valor não estiver correto para o campo especificado.

  • Se um campo tiver um representante definido no Interface Builder, o formulário não o altera. Não vejo muitos motivos para definir um delegado diferente para um campo específico, mas por que não…

Há várias maneiras de melhorar essa classe de exibição de formulário - Anexe um delegado, faça um layout, manipule quando os teclados cobrem um campo (usando o quadro currentEditingTextField), inicie automaticamente a edição para o próximo campo, ...

Pessoalmente, eu o mantenho no meu framework, e sempre o subclasse para adicionar recursos, geralmente é útil "como está".

Espero que ajude. Cheers all

alce
fonte
1
Aula útil. Um pequeno ponto, você não deve prefixar suas próprias classes com "UI". No objetivo-c, você deve usar seu próprio prefixo ("TL"?); No Swift, não use nada.
Kubi # 10/15
Obrigado @kubi. Está certo. É MF no meu quadro, como MooseFactory;)
Moose
1

se você quiser toda a edição de um UIViewController, poderá usar.

[[self view]endEditing:YES];

e se você deseja descartar uma ocultação de teclado UITextField em particular, use.

1. adicione delegado no seu viewcontroller.h

<UITextFieldDelegate>
  1. torne a delegação incapaz para o seu campo de texto.

    self.yourTextField.delegate = self;

  2. adicione esse método ao seu viewcontroller.

    - (BOOL) textFieldShouldEndEditing: (UITextField *) textField {[textField resignFirstResponder]; retornar SIM;}

Abhimanyu Rathore
fonte
1

Defina programaticamente o delegado do UITextField em 3 segundos

Implemente UITextFieldDelegate no seu arquivo ViewController.Swift (por exemplo, classe ViewController: UIViewController, UITextFieldDelegate {)

 lazy var firstNameTF: UITextField = {

    let firstname = UITextField()
    firstname.placeholder = "FirstName"
    firstname.frame = CGRect(x:38, y: 100, width: 244, height: 30)
    firstname.textAlignment = .center
    firstname.borderStyle = UITextBorderStyle.roundedRect
    firstname.keyboardType = UIKeyboardType.default
    firstname.delegate = self
    return firstname
}()

lazy var lastNameTF: UITextField = {

    let lastname = UITextField()
    lastname.placeholder = "LastName"
    lastname.frame = CGRect(x:38, y: 150, width: 244, height: 30)
    lastname.textAlignment = .center
    lastname.borderStyle = UITextBorderStyle.roundedRect
    lastname.keyboardType = UIKeyboardType.default
    lastname.delegate = self
    return lastname
}()

lazy var emailIdTF: UITextField = {

    let emailid = UITextField()
    emailid.placeholder = "EmailId"
    emailid.frame = CGRect(x:38, y: 200, width: 244, height: 30)
    emailid.textAlignment = .center
    emailid.borderStyle = UITextBorderStyle.roundedRect
    emailid.keyboardType = UIKeyboardType.default
    emailid.delegate = self
    return emailid
}()

// Mark: - manipulando delegado textField ..

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    view.endEditing(true)
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

    if textField == firstNameTF {

        lastNameTF.becomeFirstResponder()
    }

    else if textField == lastNameTF {

        emailIdTF.becomeFirstResponder()
    }
    else {
        view.emailIdTF(true)
    }
    return true
}
Tanjima Kothiya
fonte
0

Crie um hidekeyboard de função e vincule-o ao campo de texto no arquivo .xib e selecione DidEndOnExit

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  
pooja_chaudhary
fonte
0

Se você criou a exibição usando o Interface Builder, use o seguinte Basta criar um método,

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

Apenas clique com o botão direito do mouse no campo de texto na exibição, defina o evento como Terminou ao sair e ligue-o ao método "dispensKeyboard".

O melhor guia para iniciantes é "Head First iPhone and iPad Development, 2nd Edition"

chandru
fonte
0

tente isso

- (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
{
    if ([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }
    return YES;
}
Vineesh TP
fonte
0
//====================================================
//                  textFieldShouldReturn:
//====================================================
-(BOOL) textFieldShouldReturn:(UITextField*) textField { 
    [textField resignFirstResponder];
    if(textField.returnKeyType != UIReturnKeyDone){
        [[textField.superview viewWithTag: self.nextTextField] becomeFirstResponder];
    }
    return YES;
}
Jake
fonte
0

Quem procura Swift 3

1) Verifique se o delegado do UITextField está conectado ao seu ViewController no Storyboard

2) Implemente UITextFieldDelegate no seu arquivo ViewController.Swift (por exemplo, classe ViewController: UIViewController, UITextFieldDelegate {)

3) Use o método delegado abaixo

func textFieldShouldReturn(textField: UITextField) -> Bool { 
   textField.resignFirstResponder()  
return false }
Burf2000
fonte
0

É assim que eu descarto o teclado no Swift 4.2 e funciona para mim:

    override func viewDidLoad() {
    super.viewDidLoad()

    let tap = UITapGestureRecognizer(target: self, action: 
    #selector(dismissKeyboard))

    view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    numberField.resignFirstResponder()
    }
Prakhar Prakash Bhardwaj
fonte
-2

Swift 3, iOS 9 ou superior

@IBAction private func noteFieldDidEndOnExit(_ sender: UITextField) {}

UPD: Ainda funciona bem para mim. Acho que o cara que dedicou essa resposta simplesmente não entendeu que ele precisa vincular essa ação ao UITextField no storyboard.

Artyom Devyatov
fonte
-6
textField.returnKeyType = UIReturnKeyDone;
Gal Blank
fonte