Как вы распускаете клавиатуру при редактировании UITextField


181

Я знаю, что должен сказать своему UITextField об отставке первого респондента, когда я хочу закрыть клавиатуру, но я не уверен, как узнать, когда пользователь нажал клавишу «Готово» на клавиатуре. Могу ли я посмотреть уведомление?


2
[self.view endEditing: ДА]; в штрихах начал делегат это лучшее решение
Zar E Ahmer

Ответы:


351

Я назначил делегата UITextFieldсвоего ViewControllerкласса.

В этом классе я реализовал этот метод следующим образом:

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

Посмотрите пример выше ... подключите это использование IntefaceBuilder к действию на том, что вы используете в качестве вашего контроллера ... всякий раз, когда пользователь закрывает систему ввода текста (нажимает на готово), это вызывается ...
Джейсон Коко

2
Любой из них будет работать - текстовое поле отправляет свое действие, когда пользователь нажимает клавишу Return («Готово», что угодно), а также отправляет свой делегат -textFieldShouldReturn :.
Ной Уизерспун

Кстати - это также работает для UISearchBar. Например, в моем коде у меня был член IBOutlet searchBarTusb; Когда щелкнули по моему «ключу возврата» (UIReturnKeySearch), - (void) searchBarSearchButtonClicked :, я поместил оператор [searchBarTusb resignFirstResponder]; Также обратите внимание, что ключ возврата был установлен в NIB с помощью Interface Builder.
Мобибоб

Зачем возвращаться NOвместо YES?
Юлиан

@IulianOnofrei Стандартное поведение кнопки возврата - добавить возврат строки и оставить клавиатуру на экране. Возвращаясь, NOвы избегаете добавления строки возврата к тексту.
Kubi

47

Если вы подключите событие DidEndOnExit текстового поля к действию (IBAction) в InterfaceBuilder, оно будет отправлено, когда пользователь отклонит клавиатуру (с клавишей возврата), и отправитель будет являться ссылкой на UITextField, который вызвал событие.

Например:

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

Затем в InterfaceBuilder свяжите событие DidEndOnExit текстового поля с этим действием на вашем контроллере (или всем, что вы используете для связи событий из пользовательского интерфейса). Всякий раз, когда пользователь вводит текст и отклоняет текстовое поле, контроллеру будет отправлено это сообщение.


Единственное событие, которое, похоже, может сработать, это textFieldDidEndEditing, в котором говорится, что оно отправляется только после того, как UITextField подает в отставку статус первого респондента. Как я узнаю, когда мне нужно подать в отставку статус первого респондента?
Куби

Я сожалею о терминологии ... это не фактическое уведомление (событие) ... Я собираюсь отредактировать свой ответ с быстрым примером и объяснением, так что посмотрите это :)
Джейсон Коко

1
Чтобы прояснить этот ответ, textField отправляет событие «Did End On Exit», когда вы нажимаете клавишу возврата, поэтому вам нужно связать его с вашим контроллером. Я думаю, что этот метод проще, чем тот, который я описал выше.
Куби

2
не могли бы вы отредактировать этот ответ так, чтобы в нем упоминалось, КАКОЕ событие для передачи, пожалуйста? Это явно лучше, чем установка делегата.
Дэн Розенстарк

1
Хотите поднять этот ответ, но не можете, пока в нем не упоминается событие DidEndOnExit. Кто-то с правами редактирования, пожалуйста, внесите изменения, если ОП не будет?
Джеймс Харт

32

Вы также можете создать метод в вашем контроллере

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

а затем в инспекторе подключений в IB подключите к нему событие «Did End On Exit».


1
Это почти неверно, или, по крайней мере, оно не соответствует сути. Подписываясь на DidEndOnExitсобытие, вам не нужно звонить resignFirstResponder. Вы можете проверить это, поставив символическую точку останова [UIResponder resignFirstResponder]. Обратите внимание, что даже если вы не вызовете resignFirstResponder, он все равно будет вызываться системой. Это объясняется в превосходной книге (книгах) Мэтта Нойбурга: apeth.com/iOSBook/…
Крис Коновер,

19

Куби, спасибо. Ваш код сработал. Просто чтобы быть явным (для новичков, таких как), как вы говорите, вы должны установить UITextField's' delegateравным ViewController, в котором находится текстовое поле. Вы можете сделать это где угодно. Я выбрал viewDidLoadметод.

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

Если вы добавили текстовое поле в свою раскадровку или NIB, вы также можете установить там текстовое поле delegate. Вам не нужно делать это программно, как показано выше. Любой подход работает отлично.
Роб

18

Вот трюк для получения автоматического режима отключения клавиатуры без кода вообще. В наконечнике отредактируйте прокси-объект «Первый ответчик» в инспекторе удостоверений, добавив новое действие «Первый ответчик»; давайте назовем это dummy:. Теперь подключите событие Did End on Exit текстового поля к dummy:действию прокси-объекта First Responder. Это оно! Поскольку событие «Завершить при выходе» в текстовом поле теперь содержит пару «действие - цель», текстовое поле автоматически отклоняет свою клавиатуру, когда пользователь нажимает «Возврат»; и поскольку нет штрафов за то, что не удалось найти обработчик для сообщения, отправленного по цепочке респондента, приложение не падает, даже если dummy:нигде нет реализации .


@matt Я обнаружил, что ЕСЛИ я добавляю последовательность откручивания И подключаю событие didEndOnExit, ТОГДА последовательность откручивания будет вызвана нажатием клавиши Return. Без подключения к событию переход не запускается. Отлично, а? Есть замечания? Кстати, у меня есть ваши книги по Swift (готово) и iOS10 (по 6 главе). Они мне очень помогли!
Verticon

@Verticon вопрос и ответ не имеет ничего общего с перетекает, так что я не понимаю вопрос ... :( это чисто о клавиатуре увольнением
матовый

@matt Извини, чувак. У меня была поддержка, потому что 1) я натолкнулся на этот поток, когда занимался тем, как обрабатывать ключ возврата UITextField; и 2) это была возможность пообщаться с вами (спасибо за книги). Здесь нет "вопроса". Просто отсутствие понимания с моей стороны, почему / как это работает так, как работает.
Verticon

@ Verticon Я прошу прощения за то, что не смог помочь. Не стесняйтесь сформулировать новый вопрос с дополнительной информацией (демонстрационный проект?) И напишите мне, если я могу быть полезным.
матовый


11

Просто добавь

[textField endEditing:YES];

где вы хотите отключить клавиатуру и отобразить вид выбора.


10

В Swift вы можете написать IBAction в контроллере и установить для этого действия событие « Завершить при выходе» текстового поля.

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

5

Swift 4.2 и это будет работать на 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

Вы также можете использовать

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

   [self.yourTextField resignFirstResponder];

  }

Лучший, если у вас много полей Uitextfields:

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

2

Вот что я должен был сделать, чтобы заставить его работать, и я думаю, что это необходимо для любого, у кого есть цифровая клавиатура для клавиатуры (или любой другой без кнопки готово):

  1. Я изменил UIView в ViewController на UIControl.
  2. Я создал функцию под названием

    -(IBAction)backgroundIsTapped:(id)sender

Это также было определено в файле .h.

После этого я связался с битом «приземления» для ViewController в Интерфейсном Разработчике.

В функции 'background is tapped' я поставил это:

    [answerField resignFirstResponder];

Просто не забудьте заменить answerField на имя UITextField, с которого вы хотите удалить клавиатуру (очевидно, убедитесь, что ваш UITextField определен, как показано ниже :)

    IBOutlet UITextField * <nameoftextfieldhere>;

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


..но это не так хорошо работает, если пользователь касается другого элемента управления.
Рагнариус

2

Вы заметите, что метод textFieldShouldReturn предоставляет объект текстового поля, который нажал клавишу DONE. Если вы установите TAG, вы можете включить это текстовое поле. Или вы можете отслеживать и сравнивать указатель объекта с некоторым значением члена, сохраненным его создателем.

Мой подход такой для самостоятельной работы:

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

    bool fDidResign = [textField resignFirstResponder];

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

    return fDidResign;
}

Тем временем я поставил «проверку», которая отрицает отставку. Это только для иллюстрации, поэтому, если пользователь печатает НЕТ! в поле он не уволит. Поведение было таким, как я хотел, но последовательность вывода была не такой, как я ожидал.

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

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

Следующее - мой вывод NSLog для этого отказа, сопровождаемого принятием. Вы заметите, что я возвращаю результат отставки, но я ожидал, что он вернет мне ЛОЖЬ, чтобы сообщить об этом вызывающей стороне ?! Помимо этого, он имеет необходимое поведение.

13.313 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
13.320 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
13.327 StudyKbd [109: 207] НЕТ!
13.333 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: отказался от клавиатуры
59.891 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
59.897 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
59.917 StudyKbd [109: 207] - [StudyKbdViewController doneEditText]: НЕТ
59.928 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: отказался от клавиатуры

1
Можете ли вы объяснить .. если я верну НЕТ или ДА в обоих случаях, происходят одни и те же вещи, так что зачем возвращать да в методе делегата textFieldShouldReturn
К. Джайсвал

1

Вот довольно чистый способ завершить издание ключом возврата или касанием на заднем плане.

В Интерфейсном Разработчике вставьте свои поля в представление класса UIFormView

Что делает этот класс:

  • Автоматически присоединять себя как делегат полей (либо разбудить от пера, либо добавить вручную)
  • Сохранить ссылку на текущее редактируемое поле
  • Отключить клавиатуру при возврате или коснуться в фоновом режиме

Вот код:

Интерфейс

#import <UIKit/UIKit.h>

@interface UIFormView : UIView<UITextFieldDelegate>

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

@end

Реализация

#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
  • Подклассируя форму и переопределяя textFieldValueIsValid:метод, вы можете избежать окончания редактирования, если значение не является правильным для данного поля.

  • Если у поля есть делегат, установленный в Интерфейсном Разработчике, то форма не изменяет его. Я не вижу много причин назначать другого делегата для определенного поля, но почему бы и нет ...

Есть много способов улучшить этот класс представления формы - присоединить делегат, сделать некоторую разметку, обработать, когда клавиатура покрывает поле (используя фрейм currentEditingTextField), автоматически запустить редактирование для следующего поля, ...

Я лично держу его в своей структуре и всегда делю на подклассы, чтобы добавить функции, это довольно часто полезно "как есть".

Я надеюсь, что это поможет. Ура все


1
Полезный класс. Одно маленькое замечание: вы не должны ставить перед своими классами префикс «UI». В target-c вы должны использовать свой собственный префикс («TL»?), В Swift ничего не использовать.
Куби

Спасибо @kubi. Это правильно. Это MF в моих рамках, как MooseFactory;)
Moose

1

если вы хотите все редактирование в UIViewController вы можете использовать.

[[self view]endEditing:YES];

и если вы хотите закрыть скрытую скрытую клавиатуру UITextField, используйте.

1. добавить делегата в ваш viewcontroller.h

<UITextFieldDelegate>
  1. сделать делегирование невозможным для вашего текстового поля.

    self.yourTextField.delegate = self;

  2. добавьте этот метод в ваш viewcontroller.

    - (BOOL) textFieldShouldEndEditing: (UITextField *) textField {[textField resignFirstResponder]; вернуть ДА;}


1

Программно установить делегат UITextField в Swift 3

Реализуйте UITextFieldDelegate в вашем файле ViewController.Swift (например, класс 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: - обработка делегата 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
}

0

Создайте функцию hidekeyboard и свяжите ее с текстовым полем в файле .xib и выберите DidEndOnExit

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  

0

Если вы создали представление с помощью Interface Builder, используйте следующее. Просто создайте метод,

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

Просто щелкните правой кнопкой мыши текстовое поле в представлении и установите событие как «Завершить при выходе», и подключите его к методу «dismissKeyboard».

Лучшее руководство для начинающих - "Head First iPhone и iPad Development, 2nd Edition"


0

попробуй это

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

Любой, кто ищет Swift 3

1) Убедитесь, что делегат вашего UITextField подключен к вашему ViewController в раскадровке

2) Реализуйте UITextFieldDelegate в вашем файле ViewController.Swift (например, класс ViewController: UIViewController, UITextFieldDelegate {)

3) Используйте метод делегата ниже

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

0

Вот как я отклоняю клавиатуру в Swift 4.2, и она работает для меня:

    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: у меня все еще отлично работает. Я думаю, что парень, который посвятил этот ответ, просто не понял, что ему нужно привязать это действие к UITextField на раскадровке.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.