iOS8自定義鍵盤-Object-C

創(chuàng)建Xcode項目

打開Xcode 6以上的版本并創(chuàng)建一個新項目。
工程命名可以根據(jù)個人喜好命名,這里的工程命名為Keyboard。以其為主項目,還需要對項目添加擴展。
添加一個Text Field,用于彈出自定義鍵盤。在項目中,打開Main.Storyboard文件,然后在屏幕上的默認的視圖控制器上拖放一個UITextField控件,最好拖放在視圖的上方,以防彈出的鍵盤將TextField遮擋了,無法查看輸入效果。


添加擴展

點擊File-> New -> Target,選擇在iOS/Application
Extension列表中的自定義輸入法(Custom Keyboard)。給該擴展命名為CustomKeyboard并選擇Object-C編程語言。


新建出來的文件夾中有.h/.m文件,我們自定義鍵盤就在這兩個擴展文件上進行。
此時可以直接在模擬器上運行了,在測試前,首先要對系統(tǒng)鍵盤進行設置,在模擬器中跳轉到主界面,打開設置并轉到通用->鍵盤->鍵盤。點擊“添加新鍵盤”,然后選擇CustomKeyboard,這里的鍵盤名字為你的工程名。
但是運行的結果是什么都沒有的,在鍵盤的左下角顯示“Next Keyboard”按鈕,相當于系統(tǒng)默認鍵盤上的地球按鈕,點擊切換輸入法。

添加按鈕

打開文件.h文件。在這個文件中,你會看到一個類繼承自UIInputViewController。這是管理視圖的鍵盤類。往該視圖上添加按鈕,所添加的按鈕就會在鍵盤中顯示出來。
創(chuàng)建一個添加按鈕的方法createButtonWithTitle,在此方法中新建UIButton,并根據(jù)個人喜歡對button進行設置。參數(shù)title就是各個按鈕上面顯示的字母,稍后通過數(shù)組對title進行傳值。
Button可以使用xib進行創(chuàng)建,為了節(jié)省時間,這里使用方法來進行創(chuàng)建
這個項目的開發(fā)思路是,將整個鍵盤劃分為4行,每一行的按鈕分別添加到一個視圖中,即有4個存放按鈕的視圖,最后將4個視圖添加到Keyboard視圖上。
<p><code>- (UIButton )createButtonWithTitle:(NSString)title{
UIButton*button = [UIButton buttonWithType:(UIButtonTypeSystem)];
button.frame = CGRectMake(0, 0, 20, 30);
[button setTitle:title forState:(UIControlStateNormal)];
[button sizeToFit];
button.titleLabel.font = [UIFont systemFontOfSize:15];
[button setTranslatesAutoresizingMaskIntoConstraints:false];
button.backgroundColor = [UIColor clearColor];
[button setTitleColor:[UIColor darkGrayColor] forState:(UIControlStateNormal)];
[button addTarget:self action:@selector(didTapButton:) forControlEvents:(UIControlEventTouchUpInside)];
returnbutton;
}</code></p>

上述代碼中,button添加一個方法didTapButton,此方法用于點擊button時,獲取button對應輸入的文本內容。

觸發(fā)按鈕方法

這里需要獲取用戶點擊哪個button,根據(jù)不同的按鈕執(zhí)行不同的操作。如24個字母鍵就顯示文本內容,shift鍵切換大小寫。
同時也對字母按鈕與功能按鈕進行區(qū)分,可以使用UIInputViewController的屬性textDocumentProxy的一些方法。如insertText就是將內容顯示到TextField中,deleteBackward相當于退格按鈕。
此處功能鍵上的顯示使用英文代替,自己開發(fā)的使用可以使用圖片代替。因此切換大小寫會是全部功能鍵的改變。
<p><code>//獲取點擊按鈕的title

  • (void)didTapButton:(UIButton)sender{
    NSString
    title = [sender titleForState:(UIControlStateNormal)];
    //響應觸摸事件的文本內容
    if([title isEqualToString:@"cp"] || [title isEqualToString:@"CP"]){
    self.isPressShiftKey = !self.isPressShiftKey;
    //大小寫轉換
    [self changeUpOrDown:sender];
    }

elseif ([title isEqualToString:@"dp"] || [title isEqualToString:@"DP"]){
[self.textDocumentProxy deleteBackward];
}

elseif ([title isEqualToString:@"Space"]){
[self.textDocumentProxy insertText:@" "];
}

elseif ([title isEqualToString:@"return"]){
[self.textDocumentProxy insertText:@"\n"];
}

elseif ([title isEqualToString:@"next"]){
[self advanceToNextInputMode];
}

else{
[self.textDocumentProxy insertText:title];
}

}</code></p>

添加按鈕約束

一個全鍵盤樣式的鍵盤上有24個字母,外加一些特殊的功能鍵,為了對按鈕進行布局,可以使用auto layout,VFL布局還有萬能公式布局。雖然auto layout可以采用界面添加約束,但是這么多個按鈕同時添加約束,要求添加約束的思路非常清晰,同時添加約束的界面可能非常卡頓。所以這里使用萬能公式布局,對按鈕進行一次性的添加約束。
按鈕布局代碼比較多,只要理清思路就沒問題了,注意每一個按鈕之間的關系。
<p><code>//button約束
-(void)addButtonLayoutConstraint:(NSMutableArray)buttonsandView:(UIView)keyboardView{
for(UIButton *button in buttons) {
//邊距
NSInteger space = 0;
NSInteger index = [buttons indexOfObject:button];
//關閉button自動翻譯約束的功能
button.translatesAutoresizingMaskIntoConstraints = NO;
//萬能代碼約束
//頂部約束
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:buttonattribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:keyboardViewattribute:NSLayoutAttributeTop multiplier:1.0 constant:space];
//底部約束
NSLayoutConstraint *buttomConstraint = [NSLayoutConstraint constraintWithItem:buttonattribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:keyboardViewattribute:NSLayoutAttributeBottom multiplier:1.0 constant:-space];
//右邊約束
NSLayoutConstraint *rightConstraint = nil;
//右邊約束
NSLayoutConstraint *leftConstraint = nil;
//判讀最后一個button
if (index == buttons.count - 1) {
rightConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeRightrelatedBy:NSLayoutRelationEqual toItem:keyboardView attribute:NSLayoutAttributeRightmultiplier:1.0 constant:-space];
}

else{
//當前button的下一個button的右約束
UIButton *nextButton = buttons[index + 1];
rightConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeRightrelatedBy:NSLayoutRelationEqual toItem:nextButton attribute:NSLayoutAttributeLeftmultiplier:1.0 constant:-space];
}

//左約束
if (index == 0) {
leftConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeftrelatedBy:NSLayoutRelationEqual toItem:keyboardView attribute:NSLayoutAttributeLeftmultiplier:1.0 constant:space];
}

else{
UIButton *prevtButton = buttons[index - 1];
leftConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeftrelatedBy:NSLayoutRelationEqual toItem:prevtButton attribute:NSLayoutAttributeRightmultiplier:1.0 constant:space];
}

//等寬
UIButton *firstButton = buttons[0];
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:firstButtonattribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeWidthmultiplier:1.0 constant:0];
[keyboardView addConstraint:widthConstraint];
[keyboardView addConstraints:@[topConstraint,buttomConstraint,rightConstraint,leftConstraint]];
}

}</code></p>

添加每一列約束

方法addRowsLayoutConstraint對每一行存儲按鈕的視圖添加約束,這里要注意的是當前行、上一行與下一行之間的關系,其實與為button添加約束類似。
<p><code>//row約束
-(void)addRowsLayoutConstraint:(NSArray)rowsandView:(UIView)inputView{
for(UIView *rowView in rows) {
NSInteger space = 0;
NSInteger index = [rows indexOfObject:rowView];
rowView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:rowViewattribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:inputViewattribute:NSLayoutAttributeRight multiplier:1.0 constant:-space];
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:rowViewattribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:inputViewattribute:NSLayoutAttributeLeft multiplier:1.0 constant:space];

//頂部約束
NSLayoutConstraint *topConstraint = nil;
if (index == 0) {
topConstraint = [NSLayoutConstraint constraintWithItem:rowView attribute:NSLayoutAttributeToprelatedBy:NSLayoutRelationEqual toItem:inputView attribute:NSLayoutAttributeTopmultiplier:1.0 constant:0];
}

else{
UIView *prevtRow = rows[index - 1];
topConstraint = [NSLayoutConstraint constraintWithItem:rowView attribute:NSLayoutAttributeToprelatedBy:NSLayoutRelationEqual toItem:prevtRow attribute:NSLayoutAttributeBottommultiplier:1.0 constant:0];
}

//底部約束
NSLayoutConstraint *buttomConstraint = nil;
if (index == rows.count - 1) {
buttomConstraint = [NSLayoutConstraint constraintWithItem:rowView attribute:NSLayoutAttributeBottomrelatedBy:NSLayoutRelationEqual toItem:inputView attribute:NSLayoutAttributeBottommultiplier:1.0 constant:0];
}

else{
UIView *nextRow = rows[index + 1];
buttomConstraint = [NSLayoutConstraint constraintWithItem:rowView attribute:NSLayoutAttributeBottomrelatedBy:NSLayoutRelationEqual toItem:nextRow attribute:NSLayoutAttributeTop multiplier:1.0constant:0];
}

//等高約束
UIView *firstRow = rows[0];
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:firstRowattribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:rowViewattribute:NSLayoutAttributeHeight multiplier:1.0 constant:0];
[inputView addConstraint:heightConstraint];
[inputView addConstraints:@[leftConstraint,rightConstraint,topConstraint,buttomConstraint]];
}

}</code></p>

按鈕添加對應的字符或者功能

對數(shù)組參數(shù)上的buttonTitles進行遍歷,即按鈕上顯示的字符,數(shù)組中字符串個數(shù)來創(chuàng)建按鈕。
使用一個帶參的方法createRowOfButtons,將已經存儲在數(shù)組里面的字母或符號添加到按鈕上,這里的數(shù)組分別是根據(jù)每一行的內容存儲的,即有4個存儲字母或符號的數(shù)組。同時也創(chuàng)建一個存放按鈕的視圖,并且對按鈕與視圖之間的約束進行設置。使用數(shù)組將全部的鍵存儲起來,一行一個數(shù)組。最后將數(shù)組buttons存放在一個總的數(shù)組allButtons中,用于之后遍歷鍵盤上的所有按鈕,進行大小寫轉換。
<p><code>//創(chuàng)建一行button

  • (UIView )createRowOfButtons:(NSArray)buttonTitles{
    NSMutableArraybuttons = [NSMutableArray array];
    //行視圖寬高
    UIView
    keyBoardRowView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
    //遍歷button
    for(NSString *title in buttonTitles) {
    //調用createButtonWithTitle
    UIButton *button = [self createButtonWithTitle:title];
    //將button添加到數(shù)組中
    [buttons addObject:button];
    [keyBoardRowView addSubview:button];
    }

[self.allButtonsaddObject:buttons];
//調用約束
[selfaddButtonLayoutConstraint:buttons andView:keyBoardRowView];
returnkeyBoardRowView;
}</code></p>

顯示

最后在viewDidLoad上,將顯示字符數(shù)組添加到按鈕上,并將每一行視圖添加到Keyboard視圖上,對每一行添加約束。
<p><code>- (void)viewDidLoad {
[superviewDidLoad];
self.allButtons= [NSMutableArray array];
self.isPressShiftKey= NO;
self.firstButtonRow= [NSMutableArray arrayWithObjects:@"q",@"w",@"e",@"r",@"t",@"y",@"u",@"i",@"o",@"p",nil];
self.secondButtonRow= [NSMutableArray arrayWithObjects:@"a",@"s",@"d",@"f",@"g",@"h",@"j",@"k",@"l",nil];
self.thirdButtonRow= [NSMutableArray arrayWithObjects:@"cp",@"z",@"x",@"c",@"v",@"b",@"n",@"m",@"dp",nil];
self.forthButtonRow= [NSMutableArray arrayWithObjects:@"123",@"next",@"Space",@"ch/en",@"return",nil];
UIViewFirstRow = [self createRowOfButtons:self.firstButtonRow];
UIView
SecndRow = [self createRowOfButtons:self.secondButtonRow];
UIViewThirdRow = [self createRowOfButtons:self.thirdButtonRow];
UIView
forthRow = [self createRowOfButtons:self.forthButtonRow];
NSArray*rows = @[FirstRow,SecndRow,ThirdRow,forthRow];
[self.viewaddSubview:FirstRow];
[self.viewaddSubview:SecndRow];
[self.viewaddSubview:ThirdRow];
[self.viewaddSubview:forthRow];
[selfaddRowsLayoutConstraint:rows andView:self.view];
}</code></p>

大小寫切換

點擊大小寫按鈕,觸發(fā)changeUpOrDown方法,大小寫轉換就要用到上面說的allButtons數(shù)組了,遍歷全部的按鈕,獲取按鈕上的title,并判斷按鈕當前是出于什么狀態(tài)(大寫或小寫),在對title進行字符串大小寫轉換,最后為按鈕設置title。
//大小寫轉換
<p><code>- (void)changeUpOrDown:(UIButton*)shiftKey{
for(NSArray * buttons in self.allButtons) {
for (UIButton *button in buttons) {
NSString *title = [button titleForState:UIControlStateNormal];
if (self.isPressShiftKey) {
title = [title uppercaseString];
}

else{
title = [title lowercaseString];
}

[button setTitle:title forState:(UIControlStateNormal)];
}

}

}</code></p>

最后再說兩句

這個教程只能實現(xiàn)簡單的功能,同時代碼中存在一些不完善的地方,只供參考,還是需要大家的努力。
完整代碼的下載地址:vancef/CustomKeyboard · GitHub

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容