Могу ли я определить ключ удаления, даже если UITextField пуст? - PullRequest
15 голосов
/ 11 мая 2011

Когда UITextField ничего не содержит, нажатие клавиши удаления на клавиатуре не вызовет ни один из методов UITextFieldDelegate.

Как я могу это обнаружить?

РЕДАКТИРОВАТЬ: Кажется, нет тривиального способа сделатьЭто.Наиболее полезные ссылки, которые я могу найти:

  1. UITextField: Любой способ обнаружить событие удаления клавиши, когда поле пусто?

  2. Как получить фактическую нажатие клавиши в UITextField

Короче говоря, мое решение состоит в том, чтобы поставить постоянный пробел в начале текстаполе.И внесите другие необходимые изменения (textFieldShouldReturn :, textField: shouldChangeCharactersInRange: replaceString: и т. Д.).

Ответы [ 8 ]

8 голосов
/ 18 сентября 2015

Это кажется выполнимым, создав подкласс UITextField.UITextField соответствует протоколу с именем UITextInput, который inturn соответствует другому протоколу с именем UIKeyInput.Протокол UIKeyInput имеет метод deleteBackward, который срабатывает при каждом нажатии клавиши возврата на клавиатуре.

Вот как это выглядит

Заголовок

#import <UIKit/UIKit.h>

@interface EmptyDeleteTextField : UITextField

@end

Реализация

- (void)deleteBackward
{
    NSLog_SM(@"Length: %d", (int)self.text.length);
    [super deleteBackward];
}

PS: не забудьте вызвать super, потому что вы не хотите связываться с поведением по умолчанию UITextField.

5 голосов
/ 26 сентября 2017

Я добавляю этот ответ для более полного примера в swift 3. По сути, мне нужно представление типа пин-кода, где у меня есть несколько текстовых полей, которые позволяют один символ в каждой ячейке.

вот так enter image description here Я начал с создания подкласса UITextField и протокола, который определяет новый функционал.

protocol MYDeleteActionTextFieldDelegate {
    func textFieldDidSelectDeleteButton(_ textField: UITextField) -> Void
}
class MYDeleteActionTextField: UITextField {
    var deleteDelegate: MYDeleteActionTextFieldDelegate?
    override func deleteBackward() {
        // Need to call this before super or the textfield edit may already be in place
        self.deleteDelegate?.textFieldDidSelectDeleteButton(self)
        super.deleteBackward()
    }
}

Затем вы создаете текстовые поля сновый подкласс и реализовать делегат в вашем контроллере представления.В моем случае я управляю текстовыми полями в массиве для простоты использования и разметки ячеек с помощью PureLayout.Я храню их так:

var pinFields = UITextField

Затем в viewDidLoad() я добавляю все поля выводов в массив следующим образом:

for _ in 1...6 {
            let field = EDFDeleteActionTextField.init(forAutoLayout: ())
            field.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
            field.delegate = self
            field.deleteDelegate = self
            field.textAlignment = .center
            field.font = UIFont.newBigTitle()
            field.textColor = UIColor.edfBlue()
            field.backgroundColor = UIColor.edfWhite()
            self.pinFields.append(field)
            self.pinView.addSubview(field)
        }

Теперь выпросто нужно ответить на все соответствующие методы делегата и цель textFieldDidChange, которая была добавлена ​​выше.

// MARK: UITextFieldDelegate
    func textFieldDidChange(textField: UITextField) {
        // If the user typed one character, move to the next cell.
        if (textField.text?.characters.count == 1) {
            let index = pinFields.index(of: textField)
            textField.resignFirstResponder()
            if (pinFields.count > index! + 1) {
                pinFields[index! + 1].becomeFirstResponder()
            }
        } // If they deleted the character move to previous cell
        else if (textField.text?.characters.count == 0) {
            let index = pinFields.index(of: textField)
            if (index! - 1 >= 0) {
                pinFields[index! - 1].becomeFirstResponder()
            }
        }
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if range.location > 0 {
            let index = pinFields.index(of: textField)
            // If there is already text in the text field and the next cell is empty - move the newly typed character to that cell.
            if (pinFields.count > index! + 1) {
                let nextField = pinFields[index! + 1]
                if (nextField.text?.characters.count == 0) {
                    textField.resignFirstResponder()
                    nextField.becomeFirstResponder()
                    nextField.text = string
                }
            }
            return false
        }
        return true
    }

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

    // MARK: EDFDeleteActionTextFieldDelegate
    func textFieldDidSelectDeleteButton(_ textField: UITextField) {
        // If user clicked delete, and there are no characters, move to previous cell if available.
        // If there are characters, it is handled in UITextFieldDelegate
        if (textField.text?.characters.count == 0) {
            let index = pinFields.index(of: textField)
            if (index! - 1 >= 0) {
                pinFields[index! - 1].becomeFirstResponder()
            }
            else {
                textField.resignFirstResponder()
            }
        }
    }

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

Счастливого кодирования.

4 голосов
/ 29 июня 2016

Это можно реализовать, создав подкласс UITextField и добавив его в качестве пользовательского класса нужного текстового поля.Затем переопределите метод "deleteBackward". Этот метод будет перехватывать все события возврата.

Код в Swift:

override func deleteBackward() {
        super.deleteBackward()
        // Enter your stuff here
    }

Также убедитесь, что вы также вызываете супер метод, как это происходит.основные функциональные возможности мероприятия.

4 голосов
/ 19 июня 2012

Хорошо, я понял это. так в - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text метод делегата (т. е. когда вводится текст) вы просто делаете

if (text.length <= 0) {
    // backspace
    return FALSE;
} else {

потому что для backspace text.length будет == 0, а для всего остального будет == 1.

1 голос
/ 11 мая 2011

Я не уверен, но вы можете попробовать пользовательский метод, используя addTarget: action: forControlEvents:. Попробуйте вариант UIControlEventAllEditingEvents.

1 голос
/ 11 мая 2011

Можно надеть на нее кнопку, но это немного хрупко, поскольку раскладка клавиатуры может меняться в зависимости от версии iOS, и, разумеется, для разных языков существуют разные раскладки клавиатуры.

Посмотрите на документ Apple «Управление текстовыми полями и текстовыми представлениями». Я уверен, что есть способ сделать это. Это что-то вроде UITextField реализует протокол для получения ключевых событий. Одним из этих ключевых событий, вероятно, будет ключ удаления, так что вы можете переопределить любой метод, получивший их, и получить его таким образом.

1 голос
/ 11 мая 2011

Поместите невидимую кнопку поверх него.

0 голосов
/ 27 января 2014

Когда вы используете клавиатуру, очевидно, что вы записываете ее в какую-то переменную (например, UITextField, UILabel или даже глобальную строку)

Опция для определения действия удаления может быть:

  • Сохранить глобальный "int previousLengthOfText"
  • Инициируйте эту переменную как lastLengthOfText = 0;
  • поймать изменение в делегатской функции: например:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{

  • сравните длину вашей метки \ textField с этой глобальной переменной и посмотрите, был ли символ добавлен или удален.

Например:

if ([self.myTextField.text length] > previousLengthOfText) {
{
// user deleted a character - Do your action here
previousLengthOfText = [self.myTextField.text length];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...