Як відхилити клавіатуру під час редагування поля UITextField


181

Я знаю, що мені потрібно сказати моєму UITextField, щоб пішов у відставку першого відповіді, коли я хочу відхилити клавіатуру, але я не впевнений, як знати, коли користувач натиснув клавішу "Готово" на клавіатурі. Чи є сповіщення, яке я можу спостерігати?


2
[самоперегляд endEditing: ТАК]; в дотиках розпочався делегат - найкраще рішення
Зар Е Ахмер

Відповіді:


351

Я встановлюю делегата UITextFieldсвого ViewControllerкласу.

У цьому класі я реалізував цей метод наступним чином:

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

Дивіться приклад вище ... Зазначте, що використання IntefaceBuilder для дії над тим, що ви використовуєте як контролер ... кожен раз, коли користувач відхилить систему введення тексту (натискання зроблено), це буде викликано ...
Джейсон Коко

2
Будь-яке з них буде спрацьовувати - текстове поле відправляє свою дію, коли користувач натискає клавішу Return ("Готово", що завгодно), а також надсилає свого делегата -textFieldShouldReturn :.
Ной Візерспун

BTW - це також працює для UISearchBar. Наприклад, мій код у мене був член IBOutlet searchBarTusb; Коли натиснули мій ключ повернення (UIReturnKeySearch), - (недійсний) searchBarSearchButtonClicked:, я ставлю заяву [searchBarTusb resignFirstResponder]; Також врахуйте, що "ключ повернення" був встановлений в NIB за допомогою Interface Builder.
mobibob

Навіщо повертатись NOзамість YES?
Юліан Онофрей

@IulianOnofrei Типовою поведінкою кнопки повернення є додавання рядка і повернення клавіатури на екрані. Повертаючись, NOви уникаєте додавання рядка до тексту.
кубі

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
Щоб уточнити цю відповідь, текстове поле надсилає події "Здійснилося завершення виходу", коли ви натискаєте клавішу повернення, тож це вам потрібно зв’язати свій контролер. Я думаю, що цей метод легший, ніж той, який я окреслив вище.
кубі

2
чи можете ви відредагувати цю відповідь, щоб вона згадувала, ЯКУ подію подати, будь ласка? Це, очевидно, приємніше, ніж встановити делегата.
Дан Розенстарк

1
Хочете підтримати цю відповідь, але не можу, поки вона не згадає про подію DidEndOnExit. Хтось із правами редагування, будь ласка, внесіть зміни, якщо ОП не буде?
Джеймс Харт

32

Ви також можете створити метод у своєму контролері

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

а потім у Інспекторі з’єднань у IB підключіть до нього подію "Здійснено закінчення виходу".


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

Ось хитрість для автоматичного відхилення клавіатури без коду взагалі. У вікні відредагуйте проксі-об'єкт First Responder в інспекторі ідентичності, додавши нову дію першого відповіді; давайте назвемо це dummy:. Тепер підключіть подія Did End on Exit у текстовому полі до dummy:дії проксі-об'єкта First Responder. Це воно! Оскільки в текстовому полі "Кінець при виході" в текстовому полі тепер є пара дій-ціль, текстове поле автоматично відхиляє його клавіатуру, коли користувач натискає кнопку "Повернутись"; і оскільки немає штрафу за те, щоб не знайти обробника для повідомлення, відправленого в ланцюжку відповідей, додаток не виходить з ладу, навіть не реалізуючи його dummy:ніде.


@matt Я виявив, що якщо я додаю розмотуючий segue і підключаю подію didEndOnExit, ЦІЛО розкручений мозок буде спрацьовувати після натискання клавіші Return. Без підключення події сега не спрацьовує. Чудово, але так? Будь-які зауваження? BTW: У мене є ваші книги Swift (закінчено) та iOS10 (на розділі 6). Вони мені надзвичайно допомогли!
Вертикон

@Verticon питання і відповідь не має нічого спільного з мотивами, тому я не розумію питання ... :( мова йде лише про звільнення з клавіатури
мат

@matt Вибач, чоловіче. У мене була підтримка скарбнички, оскільки 1) я натрапив на цю нитку, коли я мав справу з тим, як обробити ключ повернення UITextField; і 2) це був шанс взаємодіяти з вами (thx для да книг). «Випуску» немає. Просто відсутність розуміння з мого боку про те, чому / як це працює так, як це робиться.
Вертикон

@Verticon Вибачаюся, що не зможу допомогти. Не соромтесь сформулювати нове запитання з додатковою інформацією (демонстраційний проект?) Та напишіть мені, якщо я можу бути корисним.
мат


11

Просто додайте

[textField endEditing:YES];

там, де ви хочете відключити клавіатуру та відобразити подання вибору.


10

У Swift ви можете написати IBAction у контролері та встановити подію Did End On Exit у текстовому полі на цю дію

@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.

Після цього я зв’язався з бітом 'touch down' для ViewController в Interface Builder.

У функції "фон натисканий" я ставлю це:

    [answerField resignFirstResponder];

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

    IBOutlet UITextField * <nameoftextfieldhere>;

Я знаю, що ця тема, напевно, померла давно ... але сподіваюся, що це комусь допоможе десь!


..але це не так добре, якщо користувач натискає інший елемент управління.
ragnarius

2

Ви помітите, що метод "textFieldShouldReturn" надає об'єкт текстового поля, який потрапив на клавішу ДОБРЕ. Якщо встановити 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
К. Jaiswal

1

Ось досить чистий спосіб закінчити видання клавішею Return або натисканням у фоновому режимі.

В Інтерфейс-конструктор вставте свої поля у вигляд класу 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:метод, ви можете уникнути закінчення видання, якщо значення не задане для даного поля.

  • Якщо поле має набір делегатів у Interface Builder, то форма не змінює його. Я не бачу причин для встановлення іншого делегата в певному полі, але чому б ні ...

Існує багато способів поліпшити цей клас перегляду форми - Приєднайте делегата, зробіть деякий макет, обробіть, коли клавіатури охоплюють поле (використовуючи поточний кадрEditingTextField), автоматично запускайте видання для наступного поля, ...

Я особисто зберігаю це у своїх рамках, і завжди підклас його додаю функції, він досить часто корисний "як є".

Я сподіваюся, що це допоможе. Вітаємо всіх


1
Корисний клас. Один невеликий момент, ви не повинні префіксувати власні класи з "UI". У aim-c ви повинні використовувати свій власний префікс ("TL"?), У Swift нічого не використовуйте.
кубі

Дякую @kubi. Це вірно. Це MF в моїх рамках, як MooseFactory;)
Moose

1

якщо ви хочете, щоб все редагування в UIViewController ви можете використовувати.

[[self view]endEditing:YES];

і якщо ви хочете відхилити пертикулярну приховування клавіатури UITextField, тоді використовуйте.

1.dd делегат у вашому viewcontroller.h

<UITextFieldDelegate>
  1. зробити делегацію не в змозі до вашого текстового поля

    self.yourTextField.delegate = Я;

  2. додайте цей метод у свій контролер перегляду.

    - (BOOL) textFieldShouldEndEditing: (UITextField *) textField {[textField resignFirstResponder]; повернути ТАК;}


1

Програмно встановити делегата UITextField у швидкій 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
}()

// Позначити: - обробка текстового поля делегата ..

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

Створіть панель перекладок функції та зв’яжіть її з текстовим полем у файлі .xib та виберіть DidEndOnExit

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  

0

Якщо ви створили подання за допомогою Interface Builder, використовуйте наступне Просто створіть метод,

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

Просто клацніть правою кнопкою миші текстове поле у ​​вікні перегляду та встановіть подію як «Кінець кінця при виході» та підключіть її до методу «dismissKeyboard».

Найкращий посібник для початківців - "Розробка першого iPhone та iPad, 2-е видання"


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.