Как вы распускаете клавиатуру при редактировании 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.