當(dāng)用戶(hù)點(diǎn)擊文本字段、文本視圖鸽捻、或者web視圖的字段的時(shí)候,系統(tǒng)會(huì)顯示鍵盤(pán)泽腮。你可以使用鍵盤(pán)的多中屬性來(lái)配置鍵盤(pán)的顯示樣式御蒲。在編輯會(huì)話開(kāi)始及結(jié)束的時(shí)候,你還可以管理鍵盤(pán)诊赊。因?yàn)殒I盤(pán)會(huì)遮擋你正在編輯的視圖厚满,所以管理包括了調(diào)整用戶(hù)界面抬高關(guān)注的區(qū)域,以便讓它顯示在鍵盤(pán)之上豪筝。
鍵盤(pán)和輸入法
無(wú)論用戶(hù)在何時(shí)點(diǎn)擊對(duì)象都有接受文本輸入的能力痰滋,該對(duì)象詢(xún)問(wèn)系統(tǒng)來(lái)顯示適當(dāng)?shù)逆I盤(pán)摘能⌒拢基于應(yīng)用程序的需要和用戶(hù)的語(yǔ)言首選項(xiàng)敲街,系統(tǒng)可以顯示多中不同的鍵盤(pán)中的一種。雖然app不能控制用戶(hù)的語(yǔ)言首選項(xiàng)(以及因此導(dǎo)致的鍵盤(pán)的輸入法)严望,但是它可以控制它打算使用的鍵盤(pán)屬性多艇,例如配置任意的特定鍵及其行為。
為文本對(duì)象配置鍵盤(pán)
你可以通過(guò)app的文本對(duì)象來(lái)直接配置鍵盤(pán)的屬性像吻。UITextField和UITextView類(lèi)都遵守UITextInputTraits協(xié)議峻黍,它定義了用于配置鍵盤(pán)的屬性。通過(guò)編程的方式或者在Interface Builder檢查器窗口設(shè)置這些屬性拨匆,可以讓系統(tǒng)顯示特定類(lèi)型的鍵盤(pán)姆涩。
默認(rèn)的鍵盤(pán)配置是為普通文本輸入設(shè)計(jì)的。圖4-1顯示了使用不同鍵盤(pán)設(shè)置的默認(rèn)鍵盤(pán)惭每。默認(rèn)鍵盤(pán)在開(kāi)始的時(shí)候顯示字母鍵盤(pán)骨饿,但用戶(hù)也可以把它切換到數(shù)字或者標(biāo)點(diǎn)(punctuation)鍵盤(pán)。大多數(shù)其他鍵盤(pán)提供與默認(rèn)鍵盤(pán)相似的功能台腥,同時(shí)也提供額外的特定適配按鈕來(lái)針對(duì)特殊任務(wù)宏赘。但是電話和數(shù)字鍵盤(pán)提供顯著不同的布局,用以數(shù)字輸入黎侈。
圖 4-1 幾種不同的鍵盤(pán)樣式
![Several different keyboard types](https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/Art/keyboard_types_2x.png)
想要實(shí)現(xiàn)不同用戶(hù)的語(yǔ)言首選項(xiàng)察署,iOS還提供不同輸入法和鍵盤(pán)布局來(lái)對(duì)應(yīng)不同的語(yǔ)言,它們中的一些顯示在圖 4-2中峻汉。輸入法和鍵盤(pán)布局取決于用戶(hù)的語(yǔ)言首選項(xiàng)贴汪。其中一些鍵盤(pán)的輸入是在多個(gè)階段中進(jìn)行的。
圖 4-2 幾種不同鍵盤(pán)和輸入法
為web視圖配置鍵盤(pán)
你可以為文本輸入元素配置一些鍵盤(pán)屬性休吠。例如嘶是,你可以在輸入元素的認(rèn)定中包括自動(dòng)糾錯(cuò)和自動(dòng)大寫(xiě)屬性,以指定鍵盤(pán)的行為蛛碌,就像在下面的例子中所顯示的那樣聂喇。
<input type="text" size="30" autocorrect="off" autocapitalize="on">
你還可以控制用戶(hù)點(diǎn)擊web頁(yè)中的文本字段的時(shí)候出現(xiàn)的鍵盤(pán)的類(lèi)型。要想顯示電話鍵盤(pán)蔚携、email鍵盤(pán)希太、或者URL鍵盤(pán),分別給輸入元素的類(lèi)型屬性使用tel酝蜒、email、或url關(guān)鍵字亡脑。想要顯示數(shù)字鍵盤(pán),將模型屬性值設(shè)置為" [0-9]* "或" \d* "拍屑。這些關(guān)鍵字和模型屬性是HTML5的一部分,并且在iOS中可用粉私。下面這張表顯示了每個(gè)鍵盤(pán)類(lèi)型如何顯示入篮,包括標(biāo)準(zhǔn)的鍵盤(pán)。
Text: <input type="text"></input>
Telephone: <input type="tel"></input>
URL: <input type="url"></input>
Email: <input type="email"></input>
Zip code: <input type="text" pattern="[0-9]* "></input>
管理鍵盤(pán)
盡管很多UIKit對(duì)象在用戶(hù)交互的時(shí)候自動(dòng)顯示鍵盤(pán),但app仍然有責(zé)任配置和管理鍵盤(pán)肮帐。下面這部分就是描述這些責(zé)任十酣。
接受鍵盤(pán)通知
當(dāng)鍵盤(pán)顯示或隱藏時(shí)郁轻,iOS發(fā)送下面的通知給任何注冊(cè)的觀察者:
- UIKeyboardWillShowNotification
- UIKeyboardDidShowNotification
- UIKeyboardWillHideNotification
- UIKeyboardDidHideNotification
每個(gè)鍵盤(pán)通知包括了關(guān)于鍵盤(pán)在屏幕中的尺寸和位置的信息。你可以使用UIKeyboardFrameBeginUserInfoKey 和 UIKeyboardFrameEndUserInfoKey 鍵從每個(gè)通知的userInfo字典中訪問(wèn)這些信息杨名;前者提供鍵盤(pán)開(kāi)始時(shí)的frame,后者提供鍵盤(pán)結(jié)束時(shí)的frame(均在屏幕坐標(biāo)內(nèi))沛厨。你應(yīng)該始終使用這些通知中的信息宙地,而不是假設(shè)鍵盤(pán)的尺寸或位置。不同輸入法之間的尺寸是不能保證相同的俄烁。而且在每個(gè)iOS的發(fā)布版本之間也是不同的绸栅。甚至在相同版本相同的語(yǔ)言的情況下,鍵盤(pán)的的尺寸還基于app的方向页屠。例如粹胯,圖4-3 顯示的在肖像和風(fēng)景模式中URL鍵盤(pán)的相對(duì)尺寸蓖柔。使用鍵盤(pán)通知的內(nèi)置信息確保你始終擁有正確的尺寸和位置信息。
圖 4-3 在肖像和風(fēng)景模式中鍵盤(pán)的相對(duì)尺寸
![Relative keyboard sizes in portrait and landscape modes](https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/Art/keyboard_size_2x.png)
注意:包含在userInfo字典的UIKeyboardFrameBeginUserInfoKey 和 UIKeyboardFrameEndUserInfoKey 屬性中的矩形风纠,應(yīng)該只使用它所包含的尺寸信息况鸣。在矩形交互操作中不要使用矩形的原點(diǎn)(它始終為{0.0, 0.0})。因?yàn)殒I盤(pán)是同臺(tái)的進(jìn)入位置竹观,鍵盤(pán)的實(shí)際邊框矩形隨時(shí)改變镐捧。
使用鍵盤(pán)通知的一個(gè)原因,是你可以在鍵盤(pán)出現(xiàn)的時(shí)候重定位被鍵盤(pán)遮擋的內(nèi)容臭增。關(guān)于如何處理該腳本(scenario)的信息懂酱,參見(jiàn)“移動(dòng)在鍵盤(pán)下的內(nèi)容”。
鍵盤(pán)通知的時(shí)間和視圖控制器轉(zhuǎn)換的時(shí)間之間沒(méi)有定義關(guān)系誊抛。
顯示鍵盤(pán)
當(dāng)用戶(hù)點(diǎn)擊視圖列牺,系統(tǒng)自動(dòng)注冊(cè)該視圖為第一響應(yīng)者。當(dāng)它正好是包含可編輯文本的視圖時(shí)拗窃,該視圖回味該文本開(kāi)啟一個(gè)編輯會(huì)話瞎领。在編輯會(huì)話開(kāi)始的時(shí)候,如果鍵盤(pán)還沒(méi)有顯示随夸,視圖要求系統(tǒng)顯示鍵盤(pán)九默。如果鍵盤(pán)已經(jīng)顯示,那么第一響應(yīng)者的更改會(huì)導(dǎo)致文本輸入從鍵盤(pán)重定向到新點(diǎn)擊的視圖宾毒。
因?yàn)殒I盤(pán)是在視圖成為第一響應(yīng)者的時(shí)候自動(dòng)顯示的驼修,所以你往往不需要做任何事來(lái)顯示它。但是伍俘,你可以通過(guò)調(diào)用視圖的becomeFirstResponder方法以編程的方式顯示鍵盤(pán)邪锌。調(diào)用這個(gè)方法把目標(biāo)視圖設(shè)置為第一響應(yīng)者,并可以像用戶(hù)點(diǎn)擊了視圖那樣開(kāi)始編輯進(jìn)程癌瘾。
如果app在單個(gè)屏幕上管理多個(gè)基于文本的視圖觅丰,用當(dāng)前的第一響應(yīng)者來(lái)追蹤視圖是一個(gè)好辦法,這會(huì)讓你可以在稍后關(guān)閉鍵盤(pán)妨退。
關(guān)閉鍵盤(pán)
雖然通常鍵盤(pán)顯示是自動(dòng)的妇萄,但是系統(tǒng)不會(huì)自動(dòng)的關(guān)閉鍵盤(pán)。這需要app在合適的時(shí)候來(lái)負(fù)責(zé)關(guān)閉咬荷。通常冠句,你要在用戶(hù)動(dòng)作的響應(yīng)中完成此操作。例如幸乒,當(dāng)用戶(hù)點(diǎn)擊鍵盤(pán)上的回車(chē)鍵或者完成鍵懦底,或者點(diǎn)擊app界面的其他按鈕來(lái)取消鍵盤(pán)『痹基于你對(duì)鍵盤(pán)的配置,你或許需要添加額外的控制到用戶(hù)界面,來(lái)促使鍵盤(pán)的關(guān)閉怒见。
想要關(guān)閉鍵盤(pán),你可以調(diào)用是當(dāng)前第一響應(yīng)者的基于文本的視圖的resignFirstResponder方法扮惦。當(dāng)是文本視圖注銷(xiāo)它的第一響應(yīng)者狀態(tài)的時(shí)候,它結(jié)束當(dāng)前的編輯會(huì)話亲桦,通知它的委托崖蜜,并關(guān)閉鍵盤(pán)。換句話說(shuō)客峭,如果你有一個(gè)被稱(chēng)為myTextField的UITextField的對(duì)象是當(dāng)前的第一響應(yīng)者豫领,想要關(guān)閉鍵盤(pán)只需做如下操作:
[myTextField resignFirstResponder];
從這一刻開(kāi)始的所有處理,都有文本對(duì)象自動(dòng)完成桃笙。
移動(dòng)在鍵盤(pán)下的內(nèi)容
當(dāng)要求顯示鍵盤(pán)的時(shí)候氏堤,系統(tǒng)會(huì)從屏幕的地步滑入鍵盤(pán)沙绝,并覆蓋在應(yīng)用的內(nèi)容上面搏明。因?yàn)樗趦?nèi)容的頂層,所以有可能遮擋住用戶(hù)想編輯的文本對(duì)象闪檬。當(dāng)這種情況發(fā)生的時(shí)候星著,你必須調(diào)整你的內(nèi)容,以便目標(biāo)對(duì)象可見(jiàn)粗悯。
調(diào)整內(nèi)容通常涉及到臨時(shí)調(diào)整一個(gè)或多個(gè)視圖的尺寸并定位它們虚循,以便文本對(duì)象保持可見(jiàn)。最簡(jiǎn)單的方法是把使用鍵盤(pán)的文本對(duì)象嵌套在UIScrollView對(duì)象里面(或者它的子類(lèi)中样傍,例如UITableView)横缔。當(dāng)鍵盤(pán)顯示的時(shí)候,你所需要做的指示重置滾動(dòng)視圖的內(nèi)容區(qū)域衫哥,并把文本對(duì)象滾動(dòng)到想要的位置茎刚。因此,在對(duì)UIKeyboardDidShowNotification的響應(yīng)中撤逢,你的處理程序方法要執(zhí)行如下操作:
- 獲得鍵盤(pán)的尺寸膛锭。
- 根據(jù)鍵盤(pán)的高度,調(diào)整插入到滾動(dòng)視圖地底部?jī)?nèi)容蚊荣。
- 滾動(dòng)目標(biāo)文本字段到視圖中初狰。
注意:對(duì)于UITableViewController類(lèi)來(lái)說(shuō),當(dāng)在行內(nèi)編輯文本字段的時(shí)候互例,它會(huì)自動(dòng)重調(diào)尺寸并重定位表視圖奢入。請(qǐng)閱讀 Table View Programming Guide for iOS中的View Controllers 和 Navigation-Based Apps。
圖4-4 用一個(gè)簡(jiǎn)單例子說(shuō)明了前面步驟的媳叨,例子中UIScrollView對(duì)象嵌入了多個(gè)文本字段腥光。當(dāng)鍵盤(pán)出現(xiàn)的時(shí)候丁存,通知處理程序方法調(diào)整滾動(dòng)視圖的內(nèi)容和滾動(dòng)指示器,然后使用UIScrollView的scrollRectToVisible:animated:方法來(lái)把點(diǎn)擊的文本字段(本例中是email字段)滾動(dòng)到視圖中柴我。
圖 4-4 調(diào)整內(nèi)容以容納鍵盤(pán)
![Adjusting content to accommodate the keyboard](https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/Art/keyboard_adjust_2x.png)
代碼清單4-1 展示了注冊(cè)鍵盤(pán)通知的代碼解寝,也展示了這些方法的處理程序方法。該代碼通過(guò)管理滾動(dòng)視圖的視圖控制器實(shí)現(xiàn)艘儒,并且滾動(dòng)視圖變量是一個(gè)outlet聋伦,它指向一個(gè)滾動(dòng)視圖對(duì)象。keyboardWasShown: 方法從該通知的info字典中得到鍵盤(pán)的尺寸界睁,并且根據(jù)鍵盤(pán)的高度來(lái)調(diào)整滾動(dòng)視圖的底部插入內(nèi)容觉增。它還設(shè)置相同的值給滾動(dòng)視圖的scrollIndicatorInsets屬性,以便滾動(dòng)指示器不被鍵盤(pán)隱藏翻斟。注意逾礁,keyboardWillBeHidden:方法不使用鍵盤(pán)尺寸;它只是簡(jiǎn)單的將滾動(dòng)視圖的contentInset和scrollIndictorInsets屬性設(shè)置為默認(rèn)值访惜,UIEdgeInsetsZero嘹履。
如果活動(dòng)的文本字段被鍵盤(pán)隱藏,keyboardWasShown: 方法適當(dāng)調(diào)整滾動(dòng)視圖的內(nèi)容偏移债热±担活動(dòng)字段被存儲(chǔ)在一個(gè)自定義變量中(在本例中被稱(chēng)為activeField),該變量是視圖控制器的成員變量窒篱,并且在textFieldDidBeginEditing: 委托方法中設(shè)置焕刮,如代碼清單4-2所示。(在這個(gè)例子中墙杯,視圖控制器還做為文本字段的委托配并。)
代碼清單 4-1 處理鍵盤(pán)的通知
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:activeField.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
代碼清單 4-2 展示了一些額外的代碼,它通過(guò)視圖控制器用于設(shè)置并清除之前例子中的activeField變量高镐。在初始化期間溉旋,每個(gè)在界面中文本字段設(shè)置視圖控制器作為它的委托。因此避消,當(dāng)文本字段激活時(shí)低滩,它可以調(diào)用這些方法。更多關(guān)于文本字段和它的委托通知的信息岩喷,參見(jiàn) “管理文本字段和文本視圖”恕沫。
代碼清單 4-2 跟蹤活動(dòng)文本字段的額外方法
- (void)textFieldDidBeginEditing:(UITextField * )textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
你還有幾種方式可以讓滾動(dòng)視圖中的編輯區(qū)域位于鍵盤(pán)的上方。除了改變滾動(dòng)視圖的底部?jī)?nèi)容插入以外纱意,你可以通過(guò)鍵盤(pán)的高度來(lái)擴(kuò)展內(nèi)容視圖的高度婶溯,然后滾動(dòng)編輯的文本對(duì)象到視圖中。雖然你可以為此目的設(shè)置UIScrollView類(lèi)有contentSize屬性,但你還可以調(diào)整內(nèi)容視圖的frame迄委,就像代碼清單4-3中所示那樣褐筛。這段文檔也適用了setContentOffset:animated: 方法來(lái)滾動(dòng)編輯字段到視圖,這種情況下叙身,它剛剛把它滾動(dòng)到鍵盤(pán)之上渔扎。
代碼清單4-3 調(diào)整內(nèi)容視圖的frame并把字段滾動(dòng)到鍵盤(pán)之上
- (void)keyboardWasShown:(NSNotification*)aNotification {
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect bkgndRect = activeField.superview.frame;
bkgndRect.size.height += kbSize.height;
[activeField.superview setFrame:bkgndRect];
[scrollView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height) animated:YES];
}