iOS 自定義鍵盤

少年佳節(jié)倍多情吟逝,老去誰知感慨生;
不效艾符趨習俗赦肋,但祈蒲酒話升平块攒。
鬢絲日日添白頭,榴錦年年照眼明佃乘;
千載賢愚同瞬息囱井,幾人湮沒幾垂名。

UI想要的效果趣避,我...只能默默的承受著

keyBoard.png

前言

端午將近庞呕,想想再過一個小時就要回家,心里難免有點激動,但是作為一個程序猿住练,怎么也不能閑著地啰,于是想起了最近正在做的項目中關于自定義鍵盤,下面就與大家分享分享讲逛,因為時間關系亏吝,GLKeyBoard就寫的有點簡單,下面就來看看具體實現(xiàn)

思路

就以UITextField為例盏混,在API中有這么一個屬性inputView蔚鸥,當我們的UITextField成為第一響應者的時候就會彈出該view,當然我們默認情況下是系統(tǒng)默認的鍵盤许赃,所以株茶,要想自定義鍵盤,就需要在此處下功夫了图焰。

動手
  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文件鳖粟,這個布局代碼也有點亂,大家多擔待拙绊。

  1. 寫完之后向图,激動的我趕快想看下效果,于是飛快的寫下了下面的代碼
    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];

正當我興奮不已的時候标沪,我艸榄攀,什么鬼,點了按鈕都沒反應金句,恍然大悟檩赢,原來按鈕點擊那里什么都沒處理....

  1. 進入按鈕點擊后的核心處理
    首先,我們的在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啦钢猛,來看看效果

init.png

嗯哼,怎么感覺不對呢轩缤?

  1. 位置不對
  2. 鍵盤上面怎么多了一截呢命迈?

排查后,才發(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具體展示的是那個

point.png

網(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é)語

關于自定義鍵盤,就差不多這么粗恢,希望大家能喜歡柑晒,要放假了,祝大家端午快樂~回家包包子去了....

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末眷射,一起剝皮案震驚了整個濱河市匙赞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌妖碉,老刑警劉巖罚屋,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嗅绸,居然都是意外死亡脾猛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門鱼鸠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猛拴,“玉大人,你說我怎么就攤上這事蚀狰∮淅ィ” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵麻蹋,是天一觀的道長跛溉。 經(jīng)常有香客問我,道長扮授,這世上最難降的妖魔是什么芳室? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮刹勃,結(jié)果婚禮上堪侯,老公的妹妹穿的比我還像新娘。我一直安慰自己荔仁,他們只是感情好伍宦,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布芽死。 她就那樣靜靜地躺著,像睡著了一般次洼。 火紅的嫁衣襯著肌膚如雪关贵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天卖毁,我揣著相機與錄音坪哄,去河邊找鬼。 笑死势篡,一個胖子當著我的面吹牛翩肌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播禁悠,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼念祭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了碍侦?” 一聲冷哼從身側(cè)響起粱坤,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瓷产,沒想到半個月后站玄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡濒旦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年株旷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尔邓。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡晾剖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出梯嗽,到底是詐尸還是另有隱情齿尽,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布灯节,位于F島的核電站循头,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏炎疆。R本人自食惡果不足惜卡骂,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望磷雇。 院中可真熱鬧偿警,春花似錦、人聲如沸唯笙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽崩掘。三九已至七嫌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苞慢,已是汗流浹背诵原。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留挽放,地道東北人绍赛。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像辑畦,于是被迫代替她去往敵國和親吗蚌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容

  • (一)Masonry介紹 Masonry是一個輕量級的布局框架 擁有自己的描述語法 采用更優(yōu)雅的鏈式語法封裝自動布...
    木易林1閱讀 2,334評論 0 3
  • Masonry是一個輕量級的布局框架纯出,擁有自己的描述語法蚯妇,采用更優(yōu)雅的鏈式語法封裝自動布局,簡潔明了并具有高可讀性...
    3dcc6cf93bb5閱讀 1,765評論 0 1
  • iOS_autoLayout_Masonry 概述 Masonry是一個輕量級的布局框架與更好的包裝AutoLay...
    指尖的跳動閱讀 1,162評論 1 4
  • 一暂筝、前言 關于蘋果的布局一直是我比較糾結(jié)的問題箩言,是寫代碼來控制布局,還是使用storyboard來控制布局呢焕襟?以前...
    iplaycodex閱讀 2,449評論 0 1
  • 當彈出鍵盤時陨收,自定義鍵盤上方的view,有三種解決辦法: 一個就是利用UITextField或者UITextVie...
    雪中夜歸人閱讀 7,233評論 1 6