Jak zdjąć klawiaturę podczas edycji pola UITextField


181

Wiem, że muszę powiedzieć mojemu UITextField, aby zrezygnował z pierwszego odpowiadania, kiedy chcę zwolnić klawiaturę, ale nie jestem pewien, skąd mam wiedzieć, kiedy użytkownik nacisnął klawisz „Gotowe” na klawiaturze. Czy jest jakieś powiadomienie, na które mogę zwrócić uwagę?


2
[self.view endEditing: YES]; w
kontakcie

Odpowiedzi:


351

Ustawiam delegata UITextFieldna moją ViewControllerklasę.

W tej klasie zaimplementowałem tę metodę w następujący sposób:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return NO;
}

Zobacz powyższy przykład ... podłącz ten, który używa IntefaceBuilder do akcji na czymkolwiek, z czego korzystasz jako kontroler ... za każdym razem, gdy użytkownik odrzuci system wprowadzania tekstu (naciski zrobione), zostanie to wywołane ...
Jason Coco

2
Oba z nich będą działać - pole tekstowe wysyła swoją akcję, gdy użytkownik naciśnie klawisz Return („Gotowe”, cokolwiek), a także wysyła delegata -textFieldShouldReturn :.
Noah Witherspoon

BTW - działa to również dla UISearchBar. Na przykład mój kod miałem członka IBOutlet searchBarTusb; Po kliknięciu mojego „klawisza powrotu” (UIReturnKeySearch) - (void) searchBarSearchButtonClicked :, wstawiam instrukcję [searchBarTusb resignFirstResponder]; Zauważ też, że „klucz powrotu” został ustawiony w NIB przy użyciu Konstruktora interfejsu.
mobibob

Po co wracać NOzamiast YES?
Iulian Onofrei

@IulianOnofrei Domyślne zachowanie przycisku powrotu polega na dodaniu znaku powrotu linii i utrzymaniu klawiatury na ekranie. Zwracając NOunikniesz dodawania powrotu wiersza do tekstu.
kubi

47

Jeśli połączysz zdarzenie DidEndOnExit pola tekstowego z akcją (IBAction) w InterfaceBuilder, zostanie ono wysłane, gdy użytkownik zwolni klawiaturę (za pomocą klawisza powrotu), a nadawca będzie referencją do pola UITextField, które uruchomiło zdarzenie.

Na przykład:

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

Następnie w InterfaceBuilder połącz zdarzenie DidEndOnExit pola tekstowego z tą akcją na kontrolerze (lub czymkolwiek innym, czego używasz do łączenia zdarzeń z interfejsu użytkownika). Ilekroć użytkownik wprowadza tekst i zwalnia pole tekstowe, kontroler otrzyma tę wiadomość.


Jedynym zdarzeniem, które wydaje się, że może działać, jest textFieldDidEndEditing, co oznacza, że ​​jest wysyłane dopiero po zrezygnowaniu przez UITextField ze statusu pierwszego odpowiadającego. Skąd mam wiedzieć, kiedy muszę zrezygnować ze statusu pierwszego respondenta?
kubi

Przykro mi z powodu terminologii ... to nie jest faktyczne powiadomienie (wydarzenie) ... Zamierzam zredagować moją odpowiedź za pomocą szybkiego przykładu i wyjaśnienia, więc zobacz to :)
Jason Coco

1
Aby wyjaśnić tę odpowiedź, textField wysyła zdarzenie „Did End On Exit” po naciśnięciu klawisza return, więc to jest to, czego potrzebujesz, aby połączyć się z kontrolerem. Myślę, że ta metoda jest łatwiejsza niż ta, którą przedstawiłem powyżej.
kubi

2
czy możesz edytować tę odpowiedź, aby wspomniała, KTÓRE zdarzenie ma zostać przekazane, proszę? Jest to oczywiście przyjemniejsze niż ustawienie delegata.
Dan Rosenstark,

1
Chcesz głosować za odpowiedzią, ale nie może, dopóki nie wspomina o zdarzeniu DidEndOnExit. Ktoś z uprawnieniami do edycji proszę wprowadzić zmiany, jeśli OP nie zrobi tego?
James Hart

32

Możesz także utworzyć metodę w kontrolerze

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

a następnie w Inspektorze połączeń w IB podłącz do niego Zdarzenie „Did End On Exit”.


1
Jest to prawie niepoprawne, a przynajmniej nie trafia w sedno. Subskrybując DidEndOnExitwydarzenie, nie musisz dzwonić resignFirstResponder. Możesz to przetestować, umieszczając symboliczny punkt przerwania [UIResponder resignFirstResponder]. Zauważ, że nawet jeśli nie wywołasz resignFirstResponder, system nadal go wywołuje. Wyjaśnia to doskonała książka Matta Neuburga: apeth.com/iOSBook/…
Chris Conover

19

kubi, dzięki. Twój kod działał. Żeby było jasne (dla początkujących jak), gdy mówisz, że musisz ustawić UITextField, delegateaby były równe ViewController, w którym znajduje się pole tekstowe. Możesz to zrobić gdziekolwiek chcesz. Wybrałem viewDidLoadmetodę.

- (void)viewDidLoad 
{
    // sets the textField delegates to equal this viewController ... this allows for the keyboard to disappear after pressing done
    daTextField.delegate = self;
}

Jeśli dodałeś pole tekstowe do swojej serii ujęć lub NIB, możesz również ustawić tam pole tekstowe delegate. Nie musisz tego robić programowo, jak pokazano powyżej. Oba podejście działa dobrze.
Rob

18

Oto sztuczka polegająca na automatycznym usuwaniu klawiatury bez kodu. W stalówce edytuj obiekt proxy First Responder w Inspektorze tożsamości, dodając nową akcję pierwszego odpowiadającego; nazwijmy to dummy:. Teraz podpisz zdarzenie Did End on Exit pola tekstowego do dummy:działania obiektu proxy First Responder. Otóż ​​to! Ponieważ zdarzenie Did End on Exit w polu tekstowym ma teraz parę cel-akcja, pole tekstowe automatycznie zwalnia klawiaturę, gdy użytkownik stuknie Return; a ponieważ nie ma kary za nie znalezienie modułu obsługi wiadomości wysłanej w łańcuchu odpowiedzi, aplikacja nie ulega awarii, mimo że dummy:nigdzie nie ma implementacji .


@matt Odkryłem, że JEŻELI dodam segreg odwijający ORAZ połączę zdarzenie didEndOnExit, TO Segment odprężający zostanie uruchomiony po naciśnięciu klawisza Return. Bez połączenia ze zdarzeniem segue nie jest wyzwalane. Świetnie, ale co? Jakieś uwagi? BTW: Mam twoje książki Swift (gotowe) i iOS10 (na rozdz. 6). Ogromnie mi pomogli!
Verticon

@Verticon pytanie i odpowiedź nie ma nic wspólnego z sekwensami, więc nie rozumiem problemu ... :( chodzi tu wyłącznie o zwolnienie klawiatury
mat

@matt Przepraszamy, stary. Byłem piggy backing, ponieważ 1) natknąłem się na ten wątek, gdy miałem do czynienia z tym, jak obsługiwać klawisz powrotu UITextField; i 2) była to okazja do interakcji z tobą (dzięki za książki da). Nie ma „problemu”. Po prostu brak zrozumienia z mojej strony, dlaczego / jak to działa tak, jak działa.
Verticon

@Verticon Przepraszam, że nie jestem w stanie pomóc. Zapraszam do sformułowania nowego pytania z większą ilością informacji (projekt demo?) I przekreśl mnie, jeśli mogę być przydatny.
mat


11

Poprostu dodaj

[textField endEditing:YES];

gdzie chcesz wyłączyć klawiaturę i wyświetlić widok próbnika.


10

W Swift możesz napisać IBAction w kontrolerze i ustawić zdarzenie Did End On Exit pola tekstowego na tę akcję

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

5

Swift 4.2 i będzie działać w 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
    }

}

4

Możesz także użyć

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

   [self.yourTextField resignFirstResponder];

  }

Najlepszy, jeśli masz wiele pól Uitextfields:

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

2

Oto, co musiałem zrobić, aby to zadziałało i myślę, że jest to konieczne dla każdego, kto ma klawiaturę numeryczną na klawiaturę (lub inne bez gotowego przycisku:

  1. Zmieniłem UIView w ViewController na UIControl.
  2. Utworzyłem funkcję o nazwie

    -(IBAction)backgroundIsTapped:(id)sender

Zostało to również zdefiniowane w pliku .h.

Następnie połączyłem się z bitem „przyziemienia” dla ViewController w Interface Builder.

W funkcji „Tło jest stukane” umieszczam to:

    [answerField resignFirstResponder];

Pamiętaj tylko, aby zmienić „answerField” na nazwę UITextField, z którego chcesz usunąć klawiaturę (oczywiście upewnij się, że UITextField jest zdefiniowany jak poniżej :)

    IBOutlet UITextField * <nameoftextfieldhere>;

Wiem, że ten temat prawdopodobnie umarł dawno temu ... ale mam nadzieję, że to gdzieś pomoże!


.. ale to nie działa tak dobrze, jeśli użytkownik dotknie innego formantu.
ragnarius

2

Zauważysz, że metoda „textFieldShouldReturn” zapewnia obiekt pola tekstowego, który nacisnął klawisz DONE. Jeśli ustawisz TAG, możesz włączyć to pole tekstowe. Lub możesz śledzić i porównywać wskaźnik obiektu z pewną wartością elementu zapisaną przez jego twórcę.

Moje podejście jest takie jak w przypadku samokształcenia:

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

    bool fDidResign = [textField resignFirstResponder];

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

    return fDidResign;
}

Tymczasem poddaję test „walidacji”, który zaprzecza następnej rezygnacji. To jest tylko dla ilustracji, więc jeśli użytkownik wpisze NIE! w pole, nie zostanie odrzucone. Zachowanie było takie, jak chciałem, ale sekwencja wyników nie była zgodna z oczekiwaniami.

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

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

Poniżej znajduje się moje dane wyjściowe NSLog dla tej odmowy, a następnie akceptacja. Zauważysz, że zwracam wynik rezygnacji, ale spodziewałem się, że zwróci FAŁSZ do mnie, aby zgłosić się z powrotem do dzwoniącego ?! Poza tym ma niezbędne zachowanie.

13.313 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
13.320 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
13.327 StudyKbd [109: 207] NIE!
13.333 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: zrezygnował z klawiatury
59.891 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
59.897 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
59.917 StudyKbd [109: 207] - [StudyKbdViewController doneEditText]: NIE
59.928 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: zrezygnował z klawiatury

1
czy możesz wyjaśnić ... jeśli zwrócę NIE lub TAK w obu przypadkach zdarzają się te same rzeczy, więc jaka jest potrzeba zwrotu tak w textFieldShouldReturn metoda delegowania
K. Jaiswal

1

Oto całkiem czysty sposób na zakończenie edycji za pomocą klawisza Return lub dotyku w tle.

W Konstruktorze interfejsów umieść pola w widoku klasy UIFormView

Co robi ta klasa:

  • Automatycznie dołącz się jako delegat pól (obudzony z końcówki lub dodany ręcznie)
  • Zachowaj odniesienie do aktualnie edytowanego pola
  • Zwróć klawiaturę po powrocie lub dotknij w tle

Oto kod:

Berło

#import <UIKit/UIKit.h>

@interface UIFormView : UIView<UITextFieldDelegate>

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

@end

Realizacja

#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
  • Podklasując formularz i przesłaniając textFieldValueIsValid:metodę, można uniknąć końca edycji, jeśli wartość nie jest poprawna dla danego pola.

  • Jeśli pole ma delegata ustawionego w Konstruktorze interfejsów, wówczas formularz go nie zmienia. Nie widzę wielu powodów, aby ustawić innego delegata w określonej dziedzinie, ale dlaczego nie…

Istnieje wiele sposobów ulepszenia tej klasy widoku formularza - dołącz delegata, zrób układ, obsłuż, gdy klawiatury zakrywają pole (używając ramki currentEditingTextField), automatycznie rozpocznij edycję dla następnego pola, ...

Osobiście trzymam go w swoim frameworku i zawsze dzielę go na podklasy, aby dodać funkcje, jest to często przydatne w obecnej postaci.

Mam nadzieję, że to pomoże. Pozdrawiam wszystkich


1
Pomocna klasa. Jeden mały punkt, nie powinieneś poprzedzać własnych klas „UI”. W celu-c powinieneś użyć własnego prefiksu („TL”?), W Swift nic nie używaj.
kubi

Dzięki @kubi. Zgadza się. W moich ramach jest MF, jak MooseFactory;)
Moose

1

jeśli chcesz całą edycję w UIViewController możesz użyć.

[[self view]endEditing:YES];

a jeśli chcesz odrzucić okulistyczną ukrywanie klawiatury UITextField, użyj.

1. dodaj delegata w swoim viewcontroller.h

<UITextFieldDelegate>
  1. uniemożliwić przekazanie uprawnień do pola tekstowego.

    self.yourTextField.delegate = self;

  2. dodaj tę metodę do kontrolera widoku.

    - (BOOL) textFieldShouldEndEditing: (UITextField *) textField {[textField resignFirstResponder]; zwróć TAK;}


1

Programowo ustaw delegata UITextField w swift 3

Zaimplementuj UITextFieldDelegate w pliku ViewController.Swift (np. Klasa 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
}()

// Znak: - obsługa delegowanego pola tekstowego ..

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
}

0

Utwórz tablicę funkcji i połącz ją z polem tekstowym w pliku .xib i wybierz DidEndOnExit

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  

0

Jeśli widok został utworzony za pomocą Konstruktora interfejsów, użyj następujących Po prostu utwórz metodę,

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

Po prostu kliknij prawym przyciskiem myszy pole tekstowe w widoku i ustaw zdarzenie jako Did End przy wyjściu i podłącz je do metody „ISSISSKeyboard ”.

Najlepszym przewodnikiem dla początkujących jest „Opracowanie pierwszego iPhone'a i iPada, wydanie drugie”


0

Spróbuj tego

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

0
//====================================================
//                  textFieldShouldReturn:
//====================================================
-(BOOL) textFieldShouldReturn:(UITextField*) textField { 
    [textField resignFirstResponder];
    if(textField.returnKeyType != UIReturnKeyDone){
        [[textField.superview viewWithTag: self.nextTextField] becomeFirstResponder];
    }
    return YES;
}

0

Każdy, kto szuka Swift 3

1) Upewnij się, że Twój Delegat UITextField jest podłączony do ViewController w Storyboard

2) Zaimplementuj UITextFieldDelegate w pliku ViewController.Swift (np. Klasa ViewController: UIViewController, UITextFieldDelegate {)

3) Użyj metody delegowania poniżej

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

0

W ten sposób zwalniam klawiaturę w Swift 4.2 i działa ona dla mnie:

    override func viewDidLoad() {
    super.viewDidLoad()

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

    view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    numberField.resignFirstResponder()
    }

-2

Swift 3, iOS 9+

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

UPD: Nadal działa dla mnie dobrze. Myślę, że facet, który poświęcił tę odpowiedź, po prostu nie zrozumiał, że musi powiązać tę akcję z polem UITextField w scenorysie.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.