你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
首页
热门
推荐
精选
登录
|
注册
iOS 自定义键盘
立即下载
用AI写一个
该例子支持:好用才打赏哦
现在下载学习
发布时间:2017-09-07
46人
|
浏览:7619次
|
收藏
|
分享
技术:ios
运行环境:ios8+
概述
就以UITextField为例,在API中有这么一个属性inputView,当我们的UITextField成为第一响应者的时候就会弹出该view,当然我们默认情况下是系统默认的键盘,所以,要想自定义键盘,就需要在此处下功夫了。
详细
> 少年佳节倍多情,老去谁知感慨生; > 不效艾符趋习俗,但祈蒲酒话升平。 > 鬓丝日日添白头,榴锦年年照眼明; > 千载贤愚同瞬息,几人湮没几垂名。 `UI`想要的效果,我...只能默默的承受着 ![keyBoard.png](/contentImages/image/jianshu/2525768-8640a81ac8f71114.png) #### 前言 端午将近,想想再过一个小时就要回家,心里难免有点激动,但是作为一个程序猿,怎么也不能闲着,于是想起了最近正在做的项目中关于自定义键盘,下面就与大家分享分享,因为时间关系,[GLKeyBoard]就写的有点简单,下面就来看看具体实现 ##### 思路 就以`UITextField`为例,在`API`中有这么一个属性`inputView`,当我们的`UITextField`成为第一响应者的时候就会弹出该`view`,当然我们默认情况下是系统默认的键盘,所以,要想自定义键盘,就需要在此处下功夫了。 ##### 动手 1. 想必写这个界面,对各位是没有什么难度的,绝对妥妥的,十来分钟就搞定的事情,贴上部分代码 ``` -(void)initializeViewComponents { self.backgroundColor =UICOLOR_FROM_RGB_OxFF(0xbfc5ca); NSArray *array = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"0",@"千",@"万",@"十万",@"百万",@"Delete",@"清除",]; for (int i = 0; i < kKeyBoardNumber; i ++) { UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.tag = kKeyBoardTag + i; [button setBackgroundColor:UICOLOR_FROM_RGB_OxFF(0xfefefe)]; if (i == kKeyBoardNumber-2) { [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [button setBackgroundColor:UICOLOR_FROM_RGB_OxFF(0xff4238)]; }else{ [button setTitleColor:UICOLOR_FROM_RGB_OxFF(0x303030) forState:UIControlStateNormal]; } if (i > 9) { button.titleLabel.font = [UIFont systemFontOfSize:12]; }else{ button.titleLabel.font = [UIFont systemFontOfSize:15]; } button.layer.cornerRadius = 5; [button.layer setMasksToBounds:YES]; [button setTitle:array[i] forState:UIControlStateNormal]; [button addTarget:self action:@selector(keyBoardClick:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:button]; if (i == 0) { [button mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(GTReViewXFloat(kKeyBoardWidth), GTReViewXFloat(kKeyBoardHeight))); make.top.equalTo(@(GTReViewXFloat(kKeyBoardTopPadding))); make.left.equalTo(self.mas_left).offset(GTReViewXFloat(5)); }]; _lastButton = button; }else if(i < 10){ [button mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(GTReViewXFloat(kKeyBoardWidth), GTReViewXFloat(kKeyBoardHeight))); make.top.equalTo(@(GTReViewXFloat(kKeyBoardTopPadding))); make.left.equalTo(_lastButton.mas_right).offset(GTReViewXFloat(kKeyBoardMiddlePadding)); }]; _lastButton = button; }else if(i == 10){ [button mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(GTReViewXFloat(kKeyBoardBigWidth), GTReViewXFloat(kKeyBoardHeight))); make.top.equalTo(_lastButton.mas_bottom).offset((GTReViewXFloat(kKeyBoardTopPadding))); make.left.equalTo(self.mas_left).offset(GTReViewXFloat(5)); }]; _lastButton = button; }else if (i < 14 && i > 10){ [button mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(GTReViewXFloat(kKeyBoardBigWidth), GTReViewXFloat(kKeyBoardHeight))); make.top.equalTo(_lastButton.mas_top); make.left.equalTo(_lastButton.mas_right).offset(GTReViewXFloat(kKeyBoardBottomMiddlePadding)); }]; _lastButton = button; }else if (i == 14){ [button mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(GTReViewXFloat(100), GTReViewXFloat(kKeyBoardHeight))); make.top.equalTo(_lastButton.mas_top); make.left.equalTo(_lastButton.mas_right).offset(GTReViewXFloat(kKeyBoardBottomMiddlePadding)); }]; _lastButton = button; }else if (i == 15){ [button mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(GTReViewXFloat(84), GTReViewXFloat(kKeyBoardHeight))); make.top.equalTo(_lastButton.mas_top); make.left.equalTo(_lastButton.mas_right).offset(GTReViewXFloat(kKeyBoardBottomMiddlePadding)); }]; _lastButton = button; } } } ``` 这里不建议像我这样,把需要的键值写在这里,最好是新建一个`plist`文件,这个布局代码也有点乱,大家多担待。 2. 写完之后,激动的我赶快想看下效果,于是飞快的写下了下面的代码 ``` GLKeyBoard *keyBoard = [[GLKeyBoard alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, GTReViewXFloat(85))]; _textFiled = [[UITextField alloc] init]; _textFiled.delegate = (id)self; _textFiled.textColor = [UIColor orangeColor]; _textFiled.borderStyle = UITextBorderStyleRoundedRect; _textFiled.placeholder = @"随便输..."; _textFiled.inputView = keyBoard; [self.view addSubview:_textFiled]; ``` 正当我兴奋不已的时候,我艹,什么鬼,点了按钮都没反应,恍然大悟,原来按钮点击那里什么都没处理.... 3. 进入按钮点击后的核心处理 首先,我们的在`GLKeyBoard`中添加点东西 ``` //键盘点击类型 typedef NS_ENUM(NSInteger,GLKeyBoardType) { GLKeyBoardClearAll, GLKeyBoardDelete, GLKeyBoardOther }; //键盘点击事件 typedef void(^KeyBoardClickBlcok)(GLKeyBoardType keyBoardType, NSString *text); ``` 这样后,我们在点击处就可以添加下面的代码了 ``` -(void)keyBoardClick:(UIButton *)sender { NSInteger tag = sender.tag - kKeyBoardTag; switch (tag) { case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:case 10:case 11:case 12:case 13: { if (self.keyBoardClickBlock) { self.keyBoardClickBlock(GLKeyBoardOther, sender.currentTitle); } } break; case 14: { if (self.keyBoardClickBlock) { self.keyBoardClickBlock(GLKeyBoardDelete, sender.currentTitle); } } break; case 15:{ if (self.keyBoardClickBlock) { self.keyBoardClickBlock(GLKeyBoardClearAll, sender.currentTitle); } } break; default: break; } } ``` 然后我们就可以在`block`中对`textField`中进行值的处理了 一开始,我想的是在`viewcontroller`中,直接添加处理方法,根据按钮的类型,来改变值,但是这样的话,岂不是每个用到的地方都要写一篇,难免太复杂,于是我想到了`category`,这就有了`UITextField+GLKeyBoard`这个类的诞生 在该类中主要添加了一个方法 `- (void)updateText:(NSString *)text`,根据按钮点击的文字来更改输入控件的值,方法过程也不是很复杂,每个地方都有标注,相信大家看了都会明白 最主要的思想就是根据`光标`来分割两边的字符,然后将新的字符插入到光标位置,并移动光标的位置。 ``` - (void)updateText:(NSString *)text { if ([text isEqualToString:@"千"]) { [self changeTextWithNumber:1000]; }else if ([text isEqualToString:@"万"]){ [self changeTextWithNumber:10000]; }else if ([text isEqualToString:@"十万"]){ [self changeTextWithNumber:100000]; }else if ([text isEqualToString:@"百万"]){ [self changeTextWithNumber:1000000]; } else{ UITextPosition *beginning = self.beginningOfDocument;//文字的开始地方 UITextPosition *startPosition = self.selectedTextRange.start;//光标开始位置 UITextPosition *endPosition = self.selectedTextRange.end;//光标结束位置 NSInteger startIndex = [self offsetFromPosition:beginning toPosition:startPosition];//获取光标开始位置在文字中所在的index NSInteger endIndex = [self offsetFromPosition:beginning toPosition:endPosition];//获取光标结束位置在文字中所在的index // 将输入框中的文字分成两部分,生成新字符串,判断新字符串是否满足要求 NSString *originText = self.text; NSString *beforeString = [originText substringToIndex:startIndex];//从起始位置到当前index NSString *afterString = [originText substringFromIndex:endIndex];//从光标结束位置到末尾 NSInteger offset; if (![text isEqualToString:@""]) { offset = text.length; } else { // 只删除一个字符 if (startIndex == endIndex) { if (startIndex == 0) { return; } offset = -1; beforeString = [beforeString substringToIndex:(beforeString.length - 1)]; } else { //光标选中多个 offset = 0; } } NSString *newText = [NSString stringWithFormat:@"%@%@%@", beforeString, text, afterString]; self.text = newText; // 重置光标位置 UITextPosition *nowPosition = [self positionFromPosition:startPosition offset:offset]; UITextRange *range = [self textRangeFromPosition:nowPosition toPosition:nowPosition]; self.selectedTextRange = range; } } ``` 到此为止,我们的键盘就`OK`啦,来看看效果 ![init.png](/contentImages/image/jianshu/2525768-35b81ad2cbc8d3db.png) 嗯哼,怎么感觉不对呢? 1. 位置不对 2. 键盘上面怎么多了一截呢? 排查后,才发现是导入了`IQKeyboard`这个类,导致键盘默认会有个工具栏在上面,但是我们美工妹子说了,不能要,好吧,于是我查看`API`,发现了这个参数 ``` /** Automatic add IQToolbar functionality. Default is YES. */ @property(nonatomic, assign, getter = isEnableAutoToolbar) BOOL enableAutoToolbar; ``` 于是我添加了一行代码,在`vc`中 ``` //如果不需要 [[IQKeyboardManager sharedManager] setEnableAutoToolbar:NO]; ``` 瞬间就对了,那么第一个问题怎么办呢?我首先想到的就是在键盘弹出的时候去修改坐标,但是我们必须的拿到这个键盘的`view`,我显示把`GLKeyBoard *keyBoard`这个对象当作键盘来设置,然后当头一棒,不行的,完全没反应。 看来只能自己写个方法来查找我们自定义的`keyBoard`了 ``` - (UIView *)findKeyboard { UIView *keyboardView = nil; NSArray *windows = [[UIApplication sharedApplication] windows]; for (UIWindow *window in [windows reverseObjectEnumerator])//逆序效率更高,因为键盘总在上方 { keyboardView = [self findKeyboardInView:window]; if (keyboardView) { return keyboardView; } } return nil; } - (UIView *)findKeyboardInView:(UIView *)view { for (UIView *subView in [view subviews]) { NSLog(@" 打印信息:%s",object_getClassName(subView)); if (strstr(object_getClassName(subView), "UIInputSetHostView")) { return subView; } else { UIView *tempView = [self findKeyboardInView:subView]; if (tempView) { return tempView; } } } return nil; } ``` 这里有个问题要注意下,就是如果你不晓得哪个是我们的`keyBoard`,可以在`NSLog(@" 打印信息:%s",object_getClassName(subView));`这个位置打个断点,看看`view`具体展示的是那个 ![point.png](/contentImages/image/jianshu/2525768-33e2890054e13cc3.png) 网上有这样的 `if (strstr(object_getClassName(subView), "UIKeyboard")) `,经测试是不行的,我估计应该是在后面的版本中发生了变化 在找到`keyBoard`这个`view`后,一切就变的简单了 我们只需要在键盘即将弹出的通知处添加下面代码就搞定啦 ``` //键盘出现时候调用的事件 -(void) keyboadWillShow:(NSNotification *)note{ NSDictionary *info = [note userInfo]; CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];//键盘的frame keyboardFrame.origin.y = CGRectGetMaxY(_textFiled.frame) + 4.5; UIView *keyBoardView = [self findKeyboard]; [UIView animateWithDuration:0.2 animations:^{ [keyBoardView setFrame:keyboardFrame]; }]; } ``` 在这里,还遇到个小坑,就是如果`textField`是写在`cell`中的,那么添加通知,最好不要在`cell`的初始化方法中添加,建议在`textField`的代理`textFieldDidBeginEditing`中添加,因为通知是一对多的,如果在`cell`的初始化方法中添加,当有很多`cell`的时候,键盘会上下跳动,而且坐标不是你想要的坐标 #####项目文件截图: ![](/contentImages/image/20170907/WuztVD2VG8hhJvT9x0V.jpg) ##### 结语 关于自定义键盘,就差不多这么,希望大家能喜欢,要放假了,祝大家端午快乐~回家包包子去了....
本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢
感谢
0
手机上随时阅读、收藏该文章 ?请扫下方二维码
相似例子推荐
评论
作者
敷衍丶尘世
16
例子数量
614
帮助
43
感谢
评分详细
可运行:
4.5
分
代码质量:
4.5
分
文章描述详细:
4.5
分
代码注释:
4.5
分
综合:
4.5
分
作者例子
iOS 仿支付宝密码支付
iOS 九宫格手势密码
iOS CAReplicatorLayer 简单动画
iOS 之UIBezierPath
iOS 核心动画 Core Animation浅谈
iOS CoreImage之滤镜简单使用
iOS UIButton文字和图片间距随意调整
iOS 简单引导界面
iOS 两种不同的图片无限轮播
iOSQuart2D绘图之UIImage简单使用
iOS 自定义键盘
iOS 自定义转场动画浅谈
iOS Core ML与Vision初识
iOS 11之Vision人脸检测
iOS之基于FreeStreamer的简单音乐播放器(模仿QQ音乐)
iOS 音频视频图像合成那点事