一、UITextInputTraits 协议
该协议定义了一些与键盘输入相关的属性。所有支持键盘输入的对象都必须接受这个协议,目的是为了与文本输入管理系统正确地交互。
UITextField 和 UITextView ,UISearchBar都支持该协议。
- @protocol UITextInputTraits <NSObject>
- @optional
- @property(nonatomic) UITextAutocapitalizationType autocapitalizationType;
- // 定义输入文本的自动大写类型 default is UITextAutocapitalizationTypeSentences
- @property(nonatomic) UITextAutocorrectionType autocorrectionType;
- // 定义输入文本的自动更正类型 default is UITextAutocorrectionTypeDefault
- @property(nonatomic) UITextSpellCheckingType spellCheckingType NS_AVAILABLE_IOS(5_0);
- // 定义输入文本的拼写检查类型 default is UITextSpellCheckingTypeDefault;
- @property(nonatomic) UIKeyboardType keyboardType;
- // 定义键盘类型 default is UIKeyboardTypeDefault
- @property(nonatomic) UIKeyboardAppearance keyboardAppearance;
- // 定义键盘外貌类型 default is UIKeyboardAppearanceDefault
- @property(nonatomic) UIReturnKeyType returnKeyType;
- // 定义键盘returnKey的类型 default is UIReturnKeyDefault (See note under UIReturnKeyType enum)
- @property(nonatomic) BOOL enablesReturnKeyAutomatically;
- // default is NO (when YES, will automatically disable return key when text widget has zero-length contents, and will automatically enable when text widget has non-zero-length contents)
- @property(nonatomic,getter=isSecureTextEntry) BOOL secureTextEntry;
- // 输入文本是否加密 default is NO
- @end
- typedef NS_ENUM(NSInteger, UIKeyboardType) {
- UIKeyboardTypeDefault, // Default type for the current input method.
- UIKeyboardTypeASCIICapable,
- // 字母键盘 Displays a keyboard which can enter ASCII characters, non-ASCII keyboards remain active
- UIKeyboardTypeNumbersAndPunctuation, // Numbers and assorted punctuation.
- UIKeyboardTypeURL, // A type optimized for URL entry (shows . / .com prominently).
- UIKeyboardTypeNumberPad, // A number pad (0-9). Suitable for PIN entry.
- UIKeyboardTypePhonePad, // A phone pad (1-9, *, 0, #, with letters under the numbers).
- UIKeyboardTypeNamePhonePad, // A type optimized for entering a person's name or phone number.
- UIKeyboardTypeEmailAddress, // A type optimized for multiple email address entry (shows space @ . prominently).
- #if __IPHONE_4_1 <= __IPHONE_OS_VERSION_MAX_ALLOWED
- UIKeyboardTypeDecimalPad, // A number pad with a decimal point.
- #endif
- #if __IPHONE_5_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
- UIKeyboardTypeTwitter, // A type optimized for twitter text entry (easy access to @ #)
- #endif
- UIKeyboardTypeAlphabet = UIKeyboardTypeASCIICapable, // Deprecated
- };
这个属性决定了在输入文本中,是否支持拼写检查。
二、定制键盘
- @interface UIResponder (UIResponderInputViewAdditions)
- // Called and presented when object becomes first responder. Goes up the responder chain.
- @property (readonly, retain) UIView *inputView NS_AVAILABLE_IOS(3_2);
- //键盘视图,定制的键盘视图要赋值给该属性
- @property (readonly, retain) UIView *inputAccessoryView NS_AVAILABLE_IOS(3_2);
- //键盘辅助视图,即位于键盘视图上面一些额外的辅助性视图,可在上添加辅助功能键
- // If called while object is first responder, reloads inputView and inputAccessoryView. Otherwise ignored.
- - (void)reloadInputViews NS_AVAILABLE_IOS(3_2);
- @end
UITextField 和 UITextView 都提供了以上方法。
如上图所示,绿色视图为 inputAccessoryView。下面的是定制的键盘视图
示例代码如下
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- self.numberTextField = [[UITextField alloc] initWithFrame:CGRectMake(20, 120, 280, 80)];
- self.numberTextField.backgroundColor = [UIColor darkGrayColor];
- self.numberTextField.delegate = self;
- self.numberTextField.keyboardType = UIKeyboardTypeNamePhonePad;
- self.numberTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
- self.numberTextField.autocorrectionType = UITextAutocorrectionTypeNo;
- self.numberTextField.spellCheckingType = UITextSpellCheckingTypeNo;
- self.numberTextField.returnKeyType = UIReturnKeySearch;
- _inputView = [[AZStockKeyboardView alloc] initWithFrame:CGRectMake(0, 0, rect.size.width, 216)];
- _inputView.delegate = self;
- self.numberTextField.inputView = _inputView;
- UIView *accessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
- accessoryView.backgroundColor = [UIColor greenColor];
- self.numberTextField.inputAccessoryView = accessoryView;
- [self.view addSubview:self.numberTextField];
- }
切换系统键盘
- - (void)customedKeyboardDidChange
- {
- self.numberTextField.inputView = nil;
- [self.numberTextField reloadInputViews];
- }
系统键盘切换定制键盘
- - (void)systemKeyboardDidChange
- {
- self.numberTextField.inputView = _inputView;
- [self.numberTextField reloadInputViews];
- }
给定制的键盘添加系统键盘按键声音
1.定制键盘视图要继承UIView,接受 UIInputViewAudioFeedback 协议,并实现协议方法
- @interface AZStockKeyboardView : UIView<UIInputViewAudioFeedback>
- {
- }
- #pragma mark UIInputViewAudioFeedback protocol methods
- - (BOOL)enableInputClicksWhenVisible
- {
- return YES;
- }
2.在定制的键盘的按键响应的方法中,调用 [[UIDevice currentDevice] playInputClick]
- - (void)numberButtonClicked:(id)sender
- {
- [[UIDevice currentDevice] playInputClick];
- }
三、改造系统键盘
由于需要定制键盘和系统键盘互相切换,就需要将系统键盘的切换键盘的按键响应我们自己的切换键盘方法。
Apple官方并没有提供这种方法,目前可行的做法是将该按键用我们自己的创建的按键将其覆盖。
UITextEffectsWindow //键盘所在window
UIPeripheralHostView //键盘视图所在的父视图 定制的键盘视图,辅助视图都放在这个视图上面
UIKeyboardAutomatic //键盘视图
UIKeyboardImpl //自己按英文的意思理解的,键盘的实现视图
UIKeyboardLayoutStar //自己按英文的意思理解的,键盘的布局视图
UIKBKeyplaneView //
UIKBKeyView //根据description判断,是键盘的功能性按键的视图(除字母,数字之外,类似删除键,空格键等)
以上视图都有层级关系,从上到下,上面的视图是下面视图的父视图
完成覆盖按键的任务,需要获取 UIKeyboardAutomatic 视图,然后把定制的切换按键添加到该视图上
获取系统键盘视图
- - (UIView *)getSystemKeyboardView
- {
- UIView *returnView = nil;
- UIWindow *keyboardWindow = nil;
- for (UIWindow *window in [[UIApplication sharedApplication] windows])
- {
- if (![NSStringFromClass([window class]) isEqualToString:NSStringFromClass([UIWindow class])])
- {
- keyboardWindow = window;
- break;
- }
- }
- if (keyboardWindow == nil)
- return nil;
- for (UIView *firstView in [keyboardWindow subviews])
- {
- if ([[firstView description] hasPrefix:@"<UIPeripheralHostView"])
- {
- for (UIView *secondView in [firstView subviews])
- {
- if ([[secondView description] hasPrefix:@"<UIKeyboardAutomatic"])
- {
- returnView = secondView;
- }
- }
- }
- }
- return returnView;
- }
监听键盘事件
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
- ificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
向键盘视图上覆盖按键
- - (void)keyboardDidShow:(id)notification
- {
- _keyboardDefaultView = [self getSystemKeyboardView];
- if (_keyboardDefaultView)
- {
- _switchNumButton = [UIButton buttonWithType:UIButtonTypeCustom];
- [_switchNumButton setTitle:@"123" forState:UIControlStateNormal];
- [_switchNumButton setBackgroundImage:[UIImage imageNamed:@"num.png"] forState:UIControlStateNormal];
- _switchNumButton.frame = CGRectMake(1, 173, 78, 42);
- [_switchNumButton addTarget:self action:@selector(changeCutomeButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
- [_keyboardDefaultView addSubview:_switchNumButton];
- }
- }
效果如下:
注意:由于所有系统键盘都是所有程序共享的,所以在当前界面消失前,或者其他类型的输入视图调用键盘前,要将我们自己定制的按键移除。
否则,从其他应用调用该类型键盘,都可以看到我们定制的按键。
同时也应该在调用键盘前,即键盘弹出时,在用我们定制的按键覆盖之前加限定条件
- - (void)keyboardDidShow:(id)notification
- {
- _keyboardDefaultView = [self getSystemKeyboardView];
- if (_keyboardDefaultView && [_numberTextField isFirstResponder])
- {
- _switchNumButton = [UIButton buttonWithType:UIButtonTypeCustom];
- [_switchNumButton setTitle:@"123" forState:UIControlStateNormal];
- [_switchNumButton setBackgroundImage:[UIImage imageNamed:@"num.png"] forState:UIControlStateNormal];
- _switchNumButton.frame = CGRectMake(1, 173, 78, 42);
- [_switchNumButton addTarget:self action:@selector(changeCutomeButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
- [_keyboardDefaultView addSubview:_switchNumButton];
- }
- else
- {
- if (_switchNumButton) {
- [_switchNumButton removeFromSuperview];
- }
- }