少年佳節(jié)倍多情吟逝,老去誰知感慨生;
不效艾符趨習俗赦肋,但祈蒲酒話升平块攒。
鬢絲日日添白頭,榴錦年年照眼明佃乘;
千載賢愚同瞬息囱井,幾人湮沒幾垂名。
UI
想要的效果趣避,我...只能默默的承受著
前言
端午將近庞呕,想想再過一個小時就要回家,心里難免有點激動,但是作為一個程序猿住练,怎么也不能閑著地啰,于是想起了最近正在做的項目中關于自定義鍵盤,下面就與大家分享分享讲逛,因為時間關系亏吝,GLKeyBoard就寫的有點簡單,下面就來看看具體實現(xiàn)
思路
就以UITextField
為例盏混,在API
中有這么一個屬性inputView
蔚鸥,當我們的UITextField
成為第一響應者的時候就會彈出該view
,當然我們默認情況下是系統(tǒng)默認的鍵盤许赃,所以株茶,要想自定義鍵盤,就需要在此處下功夫了图焰。
動手
- 想必寫這個界面启盛,對各位是沒有什么難度的,絕對妥妥的技羔,十來分鐘就搞定的事情僵闯,貼上部分代碼
-(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
文件鳖粟,這個布局代碼也有點亂,大家多擔待拙绊。
- 寫完之后向图,激動的我趕快想看下效果,于是飛快的寫下了下面的代碼
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];
正當我興奮不已的時候标沪,我艸榄攀,什么鬼,點了按鈕都沒反應金句,恍然大悟檩赢,原來按鈕點擊那里什么都沒處理....
- 進入按鈕點擊后的核心處理
首先,我們的在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
中,直接添加處理方法趁曼,根據(jù)按鈕的類型军浆,來改變值,但是這樣的話挡闰,豈不是每個用到的地方都要寫一篇乒融,難免太復雜,于是我想到了category
,這就有了UITextField+GLKeyBoard
這個類的誕生
在該類中主要添加了一個方法
- (void)updateText:(NSString *)text
簇抵,根據(jù)按鈕點擊的文字來更改輸入控件的值庆杜,方法過程也不是很復雜,每個地方都有標注碟摆,相信大家看了都會明白
最主要的思想就是根據(jù)光標
來分割兩邊的字符晃财,然后將新的字符插入到光標位置,并移動光標的位置典蜕。
- (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;//光標結(jié)束位置
NSInteger startIndex = [self offsetFromPosition:beginning toPosition:startPosition];//獲取光標開始位置在文字中所在的index
NSInteger endIndex = [self offsetFromPosition:beginning toPosition:endPosition];//獲取光標結(jié)束位置在文字中所在的index
// 將輸入框中的文字分成兩部分断盛,生成新字符串,判斷新字符串是否滿足要求
NSString *originText = self.text;
NSString *beforeString = [originText substringToIndex:startIndex];//從起始位置到當前index
NSString *afterString = [originText substringFromIndex:endIndex];//從光標結(jié)束位置到末尾
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
啦钢猛,來看看效果
嗯哼,怎么感覺不對呢轩缤?
- 位置不對
- 鍵盤上面怎么多了一截呢命迈?
排查后,才發(fā)現(xiàn)是導入了IQKeyboard
這個類火的,導致鍵盤默認會有個工具欄在上面壶愤,但是我們美工妹子說了,不能要馏鹤,好吧征椒,于是我查看API
,發(fā)現(xiàn)了這個參數(shù)
/**
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
具體展示的是那個
網(wǎng)上有這樣的
if (strstr(object_getClassName(subView), "UIKeyboard"))
,經(jīng)測試是不行的疑枯,我估計應該是在后面的版本中發(fā)生了變化在找到
keyBoard
這個view
后辩块,一切就變的簡單了我們只需要在鍵盤即將彈出的通知處添加下面代碼就搞定啦
//鍵盤出現(xiàn)時候調(diào)用的事件
-(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
的時候掌动,鍵盤會上下跳動四啰,而且坐標不是你想要的坐標
結(jié)語
關于自定義鍵盤,就差不多這么粗恢,希望大家能喜歡柑晒,要放假了,祝大家端午快樂~回家包包子去了....