重點:
通過替換UITextField的inputView展示自定義鍵盤
獲取當前系統響應鏈第一響應者:
UIResponder並沒有提供直接獲取的方法、這裏調用sendAction:to:from:forEvent:方法。
當target爲空時、系統會遍歷響應鏈由第一響應者響應事件,這樣我們就獲取到第一響應者。
我們通過獲取到的responder實現鍵盤數字的輸入及退格操作
複製粘貼時鍵盤的切換鍵鈕狀態:
通過UIControlEventEditingChanged獲取鍵盤點擊後輸入框內容的改變
在textField:shouldChangeCharactersInRange:replacementString:獲取複製粘貼內容及進行規則判斷
//ViewController.m
#import "ViewController.h"
#import "PlateInputView.h"
#define WIDTH [UIScreen mainScreen].bounds.size.width
#define HEIGHT [UIScreen mainScreen].bounds.size.height
@interface ViewController ()<UITextFieldDelegate>
@property (nonatomic,strong)PlateInputView * plateInput;
@property (nonatomic,strong)UITextField * plateTextField;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_plateTextField = [[UITextField alloc]initWithFrame:CGRectMake(30, 100, WIDTH-60, 50)];
_plateTextField.delegate = self;
_plateTextField.layer.borderColor = [UIColor blackColor].CGColor;
_plateTextField.layer.borderWidth = 1;
_plateTextField.keyboardType = UIKeyboardTypeNumberPad;//設置數字鍵盤防止複製粘貼板自動加空格
__block ViewController * weakSelf = self;
_plateInput = [[PlateInputView alloc]init];
_plateInput.sendTextBlock = ^(NSString *palteString) {
weakSelf.plateTextField.text = palteString;
};
_plateTextField.inputView = _plateInput;
[_plateTextField addTarget:self action:@selector(textChange:) forControlEvents:UIControlEventEditingChanged];
[self.view addSubview:_plateTextField];
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapClick:)];
[self.view addGestureRecognizer:tap];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark 車牌號輸入框監聽及代理方法
-(void)textChange:(UITextField *)textField{
NSString * str = textField.text;
_plateInput.plateStr = str;
}
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSString * str = textField.text;
string = [string stringByReplacingOccurrencesOfString:@" " withString:@""];
str = [str stringByReplacingCharactersInRange:range withString:string];
if (str.length>0) {
NSArray * provinceArr = @[@"京",@"津",@"晉",@"冀",@"蒙",@"遼",@"黑",@"吉",@"滬",@"蘇",@"浙",@"皖",@"閩",@"贛",
@"魯",@"豫",@"鄂",@"湘",@"粵",@"桂",@"瓊",@"渝",@"川",@"貴",@"雲",@"藏",@"陝",@"甘",
@"青",@"寧",@"新",@"W"];
if (str.length>8) {
return NO;
}else if (![provinceArr containsObject:[str substringToIndex:1]]) {
return NO;
}else{
for (NSString * enumStr in provinceArr) {
if ([enumStr isEqualToString:@"W"]) {
}else if ([[str substringWithRange:NSMakeRange(1, str.length-1)] rangeOfString:enumStr].location != NSNotFound ) {
return NO;
}
}
}
}
_plateInput.plateStr = str;
return YES;
}
-(void)tapClick:(UITapGestureRecognizer *)tap{
[tap.view endEditing:YES];
}
@end
PlateInputView
// PlateInputView.h 文件
@interface PlateInputView : UIInputView
@property (nonatomic,weak)id<UIKeyInput> keyInput;//接收響應者、處理輸入、退格
@property (nonatomic,strong)NSString *plateStr;
@property (nonatomic,copy)void (^sendTextBlock)(NSString *plateString);//第一位不是省份簡寫時輸入框回調
-(instancetype)init;
@end
// PlateKeyBoard.m
#import "PlateInputView.h"
#define WIDTH [UIScreen mainScreen].bounds.size.width
#define HEIGHT [UIScreen mainScreen].bounds.size.height
#define INPUTHEIGHT 180 * (HEIGHT/568)
#pragma mark 獲取當前應用第一響應鏈對象
static __weak id firstResponder;
@implementation UIResponder(FirstResponder)
+ (id)firstResponder{
firstResponder = nil;
//當target爲空時、系統會默認遍歷響應鏈執行
[[UIApplication sharedApplication] sendAction:@selector(findFirstResponder:) to:nil from:nil forEvent:nil];
return firstResponder;
}
#pragma clang diagnostic pop
- (void)findFirstResponder:(id)sender{//第一響應者響應方法、設置firstResponder
firstResponder = self;
}
@end
@interface PlateInputView ()
@property (nonatomic, strong) NSArray *provinceArr;//省份簡稱
@property (nonatomic, strong) NSArray *letterArr;//尾數(數字+字母)
@property (nonatomic, strong) UIView *provinceView;//省份選擇視圖
@property (nonatomic, strong) UIView *letterView;//尾數視圖
@end
@implementation PlateInputView
-(instancetype)init{
if (self = [super init]) {
[self createInputV];
}
return self;
}
-(void)createInputV{
self.frame = CGRectMake(0, HEIGHT-INPUTHEIGHT, WIDTH, INPUTHEIGHT);
self.backgroundColor = [UIColor lightGrayColor];
_provinceArr = @[@"京",@"津",@"晉",@"冀",@"蒙",@"遼",@"黑",@"吉",@"滬",
@"蘇",@"浙",@"皖",@"閩",@"贛",@"魯",@"豫",@"鄂",@"湘",
@"粵",@"桂",@"瓊",@"渝",@"川",@"貴",@"雲",@"藏",@"陝",
@"甘",@"青",@"寧",@"新",@"W"];
_letterArr = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"0",
@"Q",@"W",@"E",@"R",@"T",@"Y",@"U",@"O",@"P",@"A",
@"S",@"D",@"F",@"G",@"H",@"J",@"K",@"L",@"學",@"Z",
@"X",@"C",@"V",@"B",@"N",@"M"];
_provinceView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, WIDTH, INPUTHEIGHT)];
[self addSubview:_provinceView];
CGFloat provinceWidth = (WIDTH) / 9;//單行數量爲9時所佔寬度
CGFloat provinceHeight = INPUTHEIGHT / 4;//單列數量爲4時所佔高度
CGFloat provinceFrameX = 0.0;//
for (int i = 0; i < _provinceArr.count+2; i++) {//數量+2爲後面添加刪除確定鍵預留
UIButton *provinceBtn = [UIButton buttonWithType:UIButtonTypeCustom];
if (i < _provinceArr.count) {
provinceBtn.frame = CGRectMake(1.5 + provinceWidth * (i%9), 1.5+ provinceHeight*(i/9), provinceWidth - 3, provinceHeight - 3);
provinceBtn.backgroundColor = [UIColor whiteColor];
[provinceBtn setTitle:_provinceArr[i] forState:0];
[provinceBtn setTitleColor:[UIColor blackColor] forState:0];
provinceFrameX = CGRectGetMaxX(provinceBtn.frame)+3;
}else if(i == _provinceArr.count){
provinceBtn.frame = CGRectMake(provinceFrameX, 1.5+ provinceHeight*(i/10), provinceWidth*1.5 - 3, provinceHeight - 3);
provinceBtn.backgroundColor = [UIColor whiteColor];
[provinceBtn setImage:[UIImage imageNamed:@"plateDelete"] forState:UIControlStateNormal];
provinceFrameX = CGRectGetMaxX(provinceBtn.frame)+3;
}else if(i == _provinceArr.count+1){
provinceBtn.frame = CGRectMake(provinceFrameX, 1.5 + provinceHeight * 3, WIDTH-provinceFrameX- 1.5, provinceHeight - 3);
provinceBtn.userInteractionEnabled = NO;
provinceBtn.backgroundColor = [UIColor grayColor];
[provinceBtn setTitle:@"確認" forState:0];
[provinceBtn setTitleColor:[UIColor whiteColor] forState:0];
}
provinceBtn.layer.cornerRadius = 3;
provinceBtn.tag = 1000 + i;
[provinceBtn addTarget:self action:@selector(provinceClick:) forControlEvents:UIControlEventTouchUpInside];
[_provinceView addSubview:provinceBtn];
}
UIView *letterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, WIDTH, INPUTHEIGHT)];
letterView.hidden = YES;
self.letterView = letterView;
[self addSubview:letterView];
CGFloat letterWidth = (WIDTH) / 10;
CGFloat letterHeight = INPUTHEIGHT / 4;
CGFloat letterFrameX = 0.0;
for (int i = 0; i < _letterArr.count+2; i++) {
UIButton *letterBtn = [UIButton buttonWithType:UIButtonTypeCustom];
if (i < _letterArr.count) {
letterBtn.frame = CGRectMake(1.5 + letterWidth * (i%10), 1.5+ letterHeight*(i/10), letterWidth - 3, letterHeight - 3);
letterBtn.backgroundColor = [UIColor whiteColor];
[letterBtn setTitle:_letterArr[i] forState:0];
[letterBtn setTitleColor:[UIColor blackColor] forState:0];
letterFrameX = CGRectGetMaxX(letterBtn.frame)+3;
}else if(i == _letterArr.count){
letterBtn.frame = CGRectMake(letterFrameX, 1.5+ letterHeight*(i/10), letterWidth*1.5 - 3, letterHeight - 3);
letterBtn.backgroundColor = [UIColor whiteColor];
[letterBtn setImage:[UIImage imageNamed:@"plateDelete"] forState:UIControlStateNormal];
letterFrameX = CGRectGetMaxX(letterBtn.frame)+3;
}else if(i == _letterArr.count+1){
letterBtn.frame = CGRectMake(letterFrameX, 1.5 + letterHeight * 3, WIDTH-letterFrameX- 1.5, letterHeight - 3);
letterBtn.userInteractionEnabled = NO;
letterBtn.backgroundColor = [UIColor grayColor];
[letterBtn setTitle:@"確認" forState:0];
[letterBtn setTitleColor:[UIColor whiteColor] forState:0];
}
letterBtn.layer.cornerRadius = 3;
letterBtn.tag = 1000 + i;
[letterBtn addTarget:self action:@selector(letterClick:) forControlEvents:UIControlEventTouchUpInside];
[letterView addSubview:letterBtn];
}
}
#pragma mark 省份點擊事件
- (void)provinceClick:(UIButton *)button{
NSInteger index = button.tag-1000;
if (index == 33){//確認
[self putAway];
}else if (index == 32){// 刪除
[self deleteText];
}else{
if (_plateStr.length<8) {
if (_plateStr.length>0) {
NSArray * provinceArr = @[@"京",@"津",@"晉",@"冀",@"蒙",@"遼",@"黑",@"吉",@"滬",@"蘇",@"浙",@"皖",@"閩",@"贛",
@"魯",@"豫",@"鄂",@"湘",@"粵",@"桂",@"瓊",@"渝",@"川",@"貴",@"雲",@"藏",@"陝",@"甘",
@"青",@"寧",@"新",@"W"];
if (![provinceArr containsObject:[_plateStr substringToIndex:1]]) {//當輸入框第一位不是省份時、拼接到第一位上、方式根據自己習慣調整
_plateStr = [NSString stringWithFormat:@"%@%@",button.titleLabel.text,_plateStr?:@""];
self.sendTextBlock(_plateStr);
}
}else{
_plateStr = button.titleLabel.text;
self.sendTextBlock(_plateStr);
}
}
self.provinceView.hidden = YES;
self.letterView.hidden = NO;
}
}
#pragma mark 尾數點擊事件
- (void)letterClick:(UIButton *)button{
NSInteger index = button.tag-1000;
if (index == 37){//確認
[self putAway];
}else if (index == 36){// 刪除
[self deleteText];
}else{
if (_plateStr.length<8) {
id <UIKeyInput>keyInput = self.keyInput;
[keyInput insertText:button.titleLabel.text];
}
}
}
#pragma mark 隱藏鍵盤
- (void)putAway{
UIResponder *firstResponder = self.keyInput;
if (firstResponder) {
[firstResponder resignFirstResponder];
}
}
#pragma mark 刪除數據
- (void)deleteText{
id <UIKeyInput> keyInput = self.keyInput;
[keyInput deleteBackward];
}
#pragma mark 外部設置輸入框文字時inputView處理
-(void)setPlateStr:(NSString *)plateStr{
_plateStr = plateStr;
if (plateStr.length>0) {
NSArray * provinceArr = @[@"京",@"津",@"晉",@"冀",@"蒙",@"遼",@"黑",@"吉",@"滬",@"蘇",@"浙",@"皖",@"閩",@"贛",@"魯",
@"豫",@"鄂",@"湘",@"粵",@"桂",@"瓊",@"渝",@"川",@"貴",@"雲",@"藏",@"陝",@"甘",@"青",@"寧",
@"新",@"W"];
if (![provinceArr containsObject:[plateStr substringToIndex:1]]) {
self.provinceView.hidden = NO;
self.letterView.hidden = YES;
}else{
self.provinceView.hidden = YES;
self.letterView.hidden = NO;
}
}else{
self.provinceView.hidden = NO;
self.letterView.hidden = YES;
}
if (plateStr.length>6) {
UIButton * button = (UIButton *)[self.provinceView viewWithTag:1033];
button.userInteractionEnabled = YES;
button.backgroundColor = [UIColor blueColor];
UIButton * button2 = (UIButton *)[self.letterView viewWithTag:1037];
button2.userInteractionEnabled = YES;
button2.backgroundColor = [UIColor blueColor];
}else{
UIButton * button = (UIButton *)[self.provinceView viewWithTag:1033];
button.userInteractionEnabled = NO;
button.backgroundColor = [UIColor grayColor];
UIButton * button2 = (UIButton *)[self.letterView viewWithTag:1037];
button2.userInteractionEnabled = NO;
button2.backgroundColor = [UIColor grayColor];
}
}
- (id<UIKeyInput>)keyInput{
id <UIKeyInput> keyInput = _keyInput;
if (keyInput) {
return keyInput;
}
keyInput = [UIResponder firstResponder];
if (![keyInput conformsToProtocol:@protocol(UITextInput)]) {
return nil;
}
_keyInput = keyInput;
return keyInput;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end