Вот моя пользовательская клавиатура, которая, как мне кажется, решает эти проблемы настолько полно, насколько это позволит Apple:
// PVKeyboard.h
#import <UIKit/UIKit.h>
@interface PVKeyboard : UIView
@property (nonatomic,assign) UITextField *textField;
@end
// PVKeyboard.m
#import "PVKeyboard.h"
@interface PVKeyboard () {
UITextField *_textField;
}
@property (nonatomic,assign) id<UITextInput> delegate;
@end
@implementation PVKeyboard
- (id<UITextInput>) delegate {
return _textField;
}
- (UITextField *)textField {
return _textField;
}
- (void)setTextField:(UITextField *)tf {
_textField = tf;
_textField.inputView = self;
}
- (IBAction)dataPress:(UIButton *)btn {
[self.delegate insertText:btn.titleLabel.text];
}
- (IBAction)backPress {
if ([self.delegate conformsToProtocol:@protocol(UITextInput)]) {
[self.delegate deleteBackward];
} else {
int nLen = [_textField.text length];
if (nLen)
_textField.text = [_textField.text substringToIndex:nLen-1];
}
}
- (IBAction)enterPress {
[_textField.delegate textFieldShouldReturn:_textField];
}
- (UIView *)loadWithNIB {
NSArray *aNib = [[NSBundle mainBundle]loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
UIView *view = [aNib objectAtIndex:0];
[self addSubview:view];
return view;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self)
[self loadWithNIB];
return self;
}
@end
В XCode 4.3 и более поздних версиях вам необходимо создать объектный класс (для файлов .h и .m) на основе UIView и файла представления пользовательского интерфейса (для файла .xib). Убедитесь, что все три файла имеют одинаковое имя. Используя Identity Inspector, убедитесь, что пользовательский класс владельца файла XIB соответствует имени нового объекта. Используя Инспектор атрибутов, установите размер формы на Свободную форму и установите для строки состояния значение «Нет». С помощью Инспектора размеров задайте размер формы, который должен соответствовать ширине стандартной клавиатуры (320 для портретной ориентации iPhone и 480 для альбомной ориентации iPhone), но вы можете выбрать любую высоту по своему усмотрению.
Форма готова к использованию. Добавьте кнопки и подключите их к dataPress, backPress и enterPress по мере необходимости. Функции initWithFrame: и loadWithNIB сделают все возможное, чтобы вы могли использовать клавиатуру, разработанную в Interface Builder.
Чтобы использовать эту клавиатуру с UITextField myTextField, просто добавьте следующий код в ваш viewDidLoad:
self.keyboard = [[PVKeyboard alloc]initWithFrame:CGRectMake(0,488,320,60)];
self.keyboard.textField = self.myTextField;
Из-за некоторых ограничений эту клавиатуру нельзя использовать повторно, поэтому вам потребуется по одной на каждое поле. Я почти могу сделать его многоразовым, но я просто не чувствую себя таким умным. Клавиатура также ограничена UITextFields, но это в основном из-за ограничений в реализации функций клавиши ввода, которые я объясню ниже.
Вот волшебство, которое должно позволить вам разработать лучшую клавиатуру, чем эта начальная структура...
Я реализовал единственное свойство этой клавиатуры, textField, используя дискретный дискретный установщик (setTextField), потому что:
- нам нужен объект UITextField для обработки проблемы ввода
- нам нужен UITextField, потому что он соответствует протоколу UITextInput, который соответствует UIKeyInput, который выполняет большую часть нашей тяжелой работы.
- это было удобное место для установки поля inputView UITextInput для использования этой клавиатуры.
Вы заметите второе частное свойство с именем delegate, которое, по сути, приводит указатель UITextField к указателю UITextInput. Я, вероятно, мог бы сделать это встроенным, но я чувствовал, что это может быть полезно в качестве функции для будущего расширения, возможно, для включения поддержки UITextView.
Функция dataPress вставляет текстовый ввод в редактируемое поле с помощью метода insertText UIKeyInput. Кажется, это работает во всех версиях, начиная с iOS 4. Для моей клавиатуры я просто использую метку каждой кнопки, что вполне нормально. Используйте любые NSStrings, которые вам понравятся.
Функция dataBack выполняет возврат и немного сложнее. Когда работает UIKeyInput deleteBackward, он работает чудесно. И хотя в документации говорится, что он работает с iOS 3.2, похоже, он работает только с iOS 5.0, когда UITextField (и UITextView) соответствует протоколу UITextInput. Так что до этого вы предоставлены сами себе. Поскольку поддержка iOS 4 беспокоит многих, я реализовал хромой backspace, который работает напрямую с UITextField. Если бы не это требование, я мог бы заставить эту клавиатуру работать с UITextView. И этот возврат не такой общий, только удаление последнего символа, в то время как deleteBackward будет работать правильно, даже если пользователь перемещает курсор.
Функция enterPress реализует клавишу ввода, но это полная ерунда, потому что Apple, похоже, не предоставляет метод для вызова клавиши ввода. Таким образом, enterPress просто вызывает функцию делегата UITextField textFieldShouldReturn:, которую реализует большинство программистов. Обратите внимание, что делегатом здесь является UITextFieldDelegate для UITextField, а НЕ свойство делегата для самой клавиатуры.
Это решение обходит обычную обработку клавиатуры, что вряд ли имеет значение в случае UITextField, но делает этот метод непригодным для использования с UITextView, поскольку теперь есть способ вставлять разрывы строк в редактируемый текст.
Вот и все. Потребовалось 24 часа чтения и копания, чтобы сделать эту работу. Я надеюсь, что это поможет кому-то.
person
Greg Young
schedule
03.11.2012