Android顯示和隱藏軟鍵盤方法

InputMethodManager類

Android中軟鍵盤的管理主要是通過(guò)InputMethodManager類來(lái)完成的。?

InputMethodManager對(duì)象的獲取方法如下:

獲取到InputMethodManager對(duì)象后就可以通過(guò)調(diào)用其成員方法來(lái)對(duì)軟鍵盤進(jìn)行操作吃靠。不過(guò)在使用InputMethodManager對(duì)象前通常都需要判斷其是否為null膊升,避免運(yùn)行時(shí)異常:

顯示軟鍵盤

Android中可以通過(guò)InputMethodManager的showSoftInput()方法來(lái)顯示軟鍵盤。?

InputMethodManager的showSoftInput()方法原型為:

它有兩個(gè)參數(shù)嫩舟,第一個(gè)參數(shù)表示當(dāng)前要接收軟鍵盤輸入的view少态,第二個(gè)參數(shù)是軟鍵盤顯示時(shí)的控制參數(shù)幻妓。使用InputMethodManager的showSoftInput()方法來(lái)顯示軟鍵盤有如下注意事項(xiàng):

? ? ????1.第一個(gè)參數(shù)中view必須是EditText帖鸦,或者EditText的子類芝薇,如果是其他類型的View、如Button作儿、TextView等洛二,showSoftInput()方法不起作用。

? ? ????2.第一個(gè)參數(shù)中的view必須是可以獲取焦點(diǎn)的(即view.isFocusable()返回true)攻锰,如果不能獲取焦點(diǎn)晾嘶,則showSoftInput()方法不起作用。EditText默認(rèn)是可獲取焦點(diǎn)的娶吞,所以此條件一般都可以滿足垒迂。如果不滿足,可以通過(guò)view.setFocusable(true);將其設(shè)置為可獲取焦點(diǎn)的view妒蛇。

? ? ????3.第一個(gè)參數(shù)中的view當(dāng)前必須已經(jīng)獲取到焦點(diǎn)(即view.isFocused()返回true)机断,如果當(dāng)前焦點(diǎn)不在該view上,則showSoftInput()方法不起作用绣夺。雖然EditText默認(rèn)是可獲取焦點(diǎn)的吏奸,但由于一個(gè)布局中可能會(huì)有多個(gè)控件可以獲取焦點(diǎn),焦點(diǎn)位置不一定會(huì)恰好在EditText上陶耍,所以此條件不一定滿足奋蔚。為了讓showSoftInput()可以起作用,必須在之前showSoftInput()前先通過(guò)view.requestFocus()獲取焦點(diǎn)烈钞。然后再執(zhí)行showSoftInput()泊碑。

? ????? 4.第一個(gè)參數(shù)中的view必須是可見(jiàn)的,即view.getVisibility()等于View.VISIBLE棵磷,如果view是不可見(jiàn)的蛾狗,無(wú)論view.getVisibility()是View.INVISIBLE還是View.GONE,showSoftInput()方法都不起作用仪媒。如果view是不可見(jiàn)的,可以先通過(guò)view.setVisibility(View.VISIBLE)將其設(shè)置為可見(jiàn)谢鹊。

? ? ????5.當(dāng)前布局必須已經(jīng)完成加載算吩,如果還未繪制完成,則showSoftInput()方法不起作用佃扼。特別的偎巢,在Activity的onCreate()中執(zhí)行showSoftInput()是不起作用的。如果要再布局文件加載后就顯示軟鍵盤兼耀,可以通過(guò)postDelayed的方式來(lái)延遲執(zhí)行showSoftInput()压昼。延遲時(shí)間不能太短求冷,一般要在50ms以上。代碼示例如下:

????????6.InputMethodManager類中提供了另外一個(gè)顯示軟鍵盤的方法showSoftInputFromInputMethod窍霞,和showSoftInput不同的是匠题,第一個(gè)參數(shù)傳入的不是一個(gè)View對(duì)象,而是一個(gè)View對(duì)象的windowToken(對(duì)一個(gè)view對(duì)象可以通過(guò)getWindowToken()的方法獲取到其windowToken但金。不過(guò)實(shí)際情況是韭山,即使上述所有條件都滿足,通過(guò)showSoftInput(view冷溃,flag)已經(jīng)可以顯示軟鍵盤钱磅,但是通過(guò)showSoftInputFromInputMethod(view.getWindowToken(), flag)仍然無(wú)法顯示軟鍵盤。

? ? ????7.參照Android官方文檔似枕,第二個(gè)參數(shù)提供一些額外的操作標(biāo)記(additional operating flags)盖淡,可以取0或者SHOW_IMPLICIT,0表示什么含義沒(méi)有說(shuō)明凿歼,SHOW_IMPLICIT表示本次顯示軟鍵盤的請(qǐng)求不是來(lái)自用戶的直接請(qǐng)求禁舷,而是隱式的請(qǐng)求。且不說(shuō)一會(huì)用數(shù)字毅往,一會(huì)用常量名牵咙,光SHOW_IMPLICIT的說(shuō)明恐怕除了這個(gè)接口的開(kāi)發(fā)人員,沒(méi)人能看懂這句話是什么意思攀唯。實(shí)際上這個(gè)參數(shù)還可以取第三個(gè)值SHOW_FORCED洁桌,直接在文檔中被遺忘了。經(jīng)過(guò)試驗(yàn)侯嘀,這個(gè)參數(shù)的取值對(duì)軟鍵盤的顯示沒(méi)有任何影響另凌,無(wú)論取哪一個(gè)值軟鍵盤都能夠正常顯示(即使隨便輸入一個(gè)整數(shù),軟鍵盤都可以顯示)戒幔。實(shí)際上這個(gè)參數(shù)影響的并不是軟鍵盤的顯示吠谢,而是軟鍵盤的隱藏。

隱藏軟鍵盤

Android在InputMethodManager類中并沒(méi)有提供一個(gè)和showSoftInput()對(duì)應(yīng)的hideSoftInput()方法來(lái)隱藏軟鍵盤诗茎,而是提供了一個(gè)showSoftInputFromInputMethod()相對(duì)應(yīng)的hideSoftInputFromWindow()方法來(lái)隱藏軟鍵盤工坊。幸運(yùn)的是,雖然showSoftInputFromInputMethod()不能正常顯示軟鍵盤敢订,hideSoftInputFromWindow()倒是能夠隱藏軟鍵盤王污。

InputMethodManager的hideSoftInputFromWindow()方法原型為:

它同樣有兩個(gè)參數(shù),第一個(gè)參數(shù)是一個(gè)View的windowToken楚午,第二個(gè)參數(shù)是軟鍵盤隱藏時(shí)的控制參數(shù)昭齐。使用?InputMethodManager的hideSoftInputFromWindow()方法來(lái)隱藏軟鍵盤有如下注意事項(xiàng):

? ? ????1.第一個(gè)參數(shù)并不是指定一個(gè)View,而是一個(gè)View的windowToken矾柜。對(duì)一個(gè)view可以通過(guò)getWindowToken()的方法獲取到其windowToken阱驾。

? ? ????2.按照官方文檔就谜,第一個(gè)參數(shù)中的windowToken應(yīng)當(dāng)是之前請(qǐng)求顯示軟鍵盤的View的windowToken,也就是執(zhí)行showSoftInput()時(shí)第一個(gè)參數(shù)中的View的windowToken里覆。但是實(shí)際情況是丧荐,用任意一個(gè)當(dāng)前布局中的已經(jīng)加載的View的windowToken都可以隱藏軟鍵盤,哪怕這個(gè)View被設(shè)置為INVISIBLE或GONE租谈。因此篮奄,如果不知道之前是誰(shuí)請(qǐng)求顯示的軟鍵盤,可以隨便傳入一個(gè)當(dāng)前布局中存在的View的windowToken割去。特別的窟却,可以傳入一個(gè)Activity的頂層View的windowToken,即getWindow().getDecorView().getWindowToken()呻逆,來(lái)隱藏當(dāng)前Activity中顯示的軟鍵盤夸赫,而不用管之前調(diào)用showSoftInput()的究竟是哪個(gè)View,示例代碼如下:

這里還要注意的是咖城,可以隨便傳入一個(gè)當(dāng)前布局中存在的View的windowToken茬腿,并不代表可以傳入任意一個(gè)View的windowToken,如下代碼不能實(shí)現(xiàn)隱藏軟鍵盤:

對(duì)新創(chuàng)建的view宜雀,必須將其加入到當(dāng)前布局中后才可以用來(lái)隱藏軟鍵盤切平。如下代碼可以實(shí)現(xiàn)隱藏軟鍵盤:

????????3.參照Android官方文檔,第二個(gè)參數(shù)同樣是提供了一些額外的操作標(biāo)記(additional operating flags)辐董,可以取0或者HIDE_IMPLICIT_ONLY悴品,0表示什么含義同樣是沒(méi)有說(shuō)明,HIDE_IMPLICIT_ONLY表示當(dāng)前的軟鍵盤應(yīng)當(dāng)只在其不是被用戶顯式的顯示的時(shí)候才隱藏(the soft input window should only be hidden if it was not explicitly shown by the user)简烘。這句話雖然很拗口苔严,但總算是有點(diǎn)有用的信息了。在顯示軟鍵盤時(shí)孤澎,可以使用的flag有0届氢,SHOW_IMPLICIT和SHOW_FORCED,參照之前的描述覆旭,當(dāng)顯示軟鍵盤指定flag為SHOW_IMPLICIT時(shí)表示隱式的顯示退子,也就是這里非用戶顯式的顯示,再參照這里的描述姐扮,如果隱藏軟鍵盤時(shí)使用的flag為HIDE_IMPLICIT_ONLY絮供,那么軟鍵盤只有在非用戶顯式的顯示的時(shí)候才隱藏,這意味著如果隱藏軟鍵盤時(shí)使用的flag為HIDE_IMPLICIT_ONLY茶敏,那么只有當(dāng)顯示軟鍵盤時(shí)指定的flag為SHOW_IMPLICIT時(shí),軟鍵盤才會(huì)隱藏缚俏,如果顯示軟鍵盤時(shí)指定的flag不是SHOW_IMPLICIT惊搏,而是0或者SHOW_FORCED贮乳,那么軟鍵盤就不會(huì)隱藏。為了更完整的看出不同flag對(duì)隱藏軟鍵盤的影響(再聲明下恬惯,無(wú)論是顯示軟鍵盤時(shí)指定的flag向拆,還是隱藏軟鍵盤時(shí)指定的flag都只對(duì)隱藏軟鍵盤有影響,對(duì)顯示軟鍵盤無(wú)影響)酪耳, 分別在調(diào)用showSoftInput()時(shí)使用三個(gè)不同的標(biāo)記浓恳,以及在調(diào)用hideSoftInputFromWindow()是使用三個(gè)不同的標(biāo)記(隱藏軟鍵盤時(shí)同樣還有一個(gè)HIDE_NOT_ALWAYS標(biāo)記,它同樣在文檔中被遺忘了)碗暗,對(duì)是否能夠隱藏軟鍵盤進(jìn)行測(cè)試颈将,測(cè)試結(jié)果如下:

(T表示可以隱藏,F(xiàn)表示不能隱藏)

可以看到言疗,在隱藏軟鍵盤時(shí)使用HIDE_IMPLICIT_ONLY標(biāo)記晴圾,確實(shí)只有在顯示軟鍵盤時(shí)使用SHOW_IMPLICIT時(shí)才會(huì)隱藏。此外噪奄,當(dāng)隱藏軟鍵盤時(shí)使用0作為標(biāo)記死姚,無(wú)論showSoftInput()時(shí)使用的是哪個(gè)參數(shù),都可以隱藏軟鍵盤勤篮。

切換軟鍵盤狀態(tài)

在InputMethodManager類中還提供了一個(gè)toggleSoftInput()的方法來(lái)在顯示和隱藏軟鍵盤之間切換都毒,也就是說(shuō),如果當(dāng)前軟鍵盤是隱藏的碰缔,那么執(zhí)行toggleSoftInput()方法時(shí)會(huì)顯示軟鍵盤账劲,如果當(dāng)前軟鍵盤是顯示的,那么執(zhí)行toggleSoftInput()方法時(shí)會(huì)隱藏軟鍵盤手负。

InputMethodManager的toggleSoftInput()方法原型為:

它同樣有兩個(gè)參數(shù)涤垫,第一個(gè)參數(shù)是顯示軟鍵盤時(shí)使用的標(biāo)記,第二個(gè)參數(shù)是隱藏軟鍵盤時(shí)使用的標(biāo)記竟终。使用InputMethodManager的toggleSoftInput()方法來(lái)切換軟鍵盤顯示狀態(tài)有如下注意事項(xiàng):

? ? ????1.showFlags為顯示軟鍵盤時(shí)使用的標(biāo)記蝠猬,只有當(dāng)前軟鍵盤處于隱藏狀態(tài)時(shí)才會(huì)使用。hideFlags是隱藏軟鍵盤時(shí)使用的標(biāo)記统捶,只有當(dāng)前軟鍵盤處于顯示狀態(tài)時(shí)才會(huì)使用榆芦。

? ? ????2.showFlags和hideFlags取值范圍,以及不同取值的影響和上文分析的一樣喘鸟。即showFlags和hideFlags都只影響軟鍵盤的隱藏匆绣,不影響軟鍵盤的顯示。不同取值對(duì)軟鍵盤隱藏的影響參見(jiàn)上文中的表格什黑。

? ? ????3.和showSoftInput()方法不同的是崎淳,使用toggleSoftInput()顯示軟鍵盤時(shí),并不要求當(dāng)前界面布局中有一個(gè)已經(jīng)獲取焦點(diǎn)的EditText愕把,即使當(dāng)前布局是完全空白的拣凹,一個(gè)View也沒(méi)有(除了最外層的Layout)森爽,toggleSoftInput()也能夠顯示軟鍵盤。不過(guò)如果沒(méi)有一個(gè)已經(jīng)獲取焦點(diǎn)的EditText嚣镜,那么軟鍵盤中的按鍵輸入都是無(wú)效的爬迟。就像這樣。

? ? ????4.顯示軟鍵盤時(shí)菊匿,要求當(dāng)前布局必須已經(jīng)加載完成付呕,如果還未繪制完成,則toggleSoftInput()方法不起作用跌捆。這點(diǎn)和之前調(diào)用showSoftInput()顯示軟鍵盤時(shí)描述的第5點(diǎn)要求是一樣的徽职。特別的,在Activity的onCreate()中執(zhí)行toggleSoftInput()必須通過(guò)postDelayed的方式來(lái)延遲執(zhí)行疹蛉。延遲時(shí)間一般要在50ms以上活箕。

? ????? 5.當(dāng)隱藏軟鍵盤時(shí),不需要知道之前觸發(fā)軟鍵盤顯示的View是哪一個(gè)或獲取當(dāng)前布局中任何一個(gè)View的windowToken可款,只要hideFlags能夠隱藏就可以育韩。由于hideFlags為0時(shí)總是能夠隱藏的,因此闺鲸,使用toggleSoftInput(0, 0)應(yīng)當(dāng)是最方便的無(wú)條件隱藏軟鍵盤的方法筋讨,前提是知道當(dāng)前軟鍵盤確實(shí)是處于顯示狀態(tài)。不過(guò)遺憾的是Android沒(méi)有任何API可以直接獲取到軟鍵盤的狀態(tài)是顯示還是隱藏的摸恍。

部分源碼解讀

顯示和隱藏軟鍵盤的源碼大都在InputMethodManagerService.java文件里悉罕。這個(gè)文件有3000多行代碼,還有很多是其他類的交互立镶,我也沒(méi)有仔細(xì)研究壁袄,這里只是將其在一些片段貼出來(lái),做一個(gè)大概的分析:

? ? 1.showSoftInput?

????showSoftInput()會(huì)進(jìn)入到showCurrentInputLocked()方法中媚媒,這里有這樣一段:

可以看到這里只是將showSoftInput的第二個(gè)參數(shù)flag和SHOW_IMPLICIT嗜逻,SHOW_FORCED相與,根據(jù)結(jié)果對(duì)mShowExplicitlyRequested和mShowForced賦值缭召。在showCurrentInputLocked()方法沒(méi)有其他用到flags的地方栈顷,也沒(méi)有用到mShowExplicitlyRequested和mShowForced。這就解釋了嵌巷,執(zhí)行showSoftInput()時(shí)傳入任意的flags都不會(huì)影響軟鍵盤的顯示萄凤。?

? ? 2.hideSoftInputFromWindow?

????hideSoftInputFromWindow會(huì)進(jìn)入hideCurrentInputLocked()方法,在hideCurrentInputLocked()方法的開(kāi)頭有這樣一段:

這里的判斷用到了隱藏軟鍵盤時(shí)使用的flags搪哪,以及mShowExplicitlyRequested和mShowForced的值靡努,如果不滿足條件就直接返回了。可以看到當(dāng)flags為HIDE_IMPLICIT_ONLY時(shí)颤难,如果mShowExplicitlyRequested和mShowForced任意一個(gè)為true神年,都會(huì)返回false已维。當(dāng)flags為HIDE_NOT_ALWAYS時(shí)行嗤,如果mShowForced為true,也會(huì)返回false垛耳,當(dāng)flags為0時(shí)栅屏,兩個(gè)if條件都不滿足。這就解釋了顯示軟鍵盤時(shí)使用的flags影響的是后面隱藏軟鍵盤是否成功堂鲜,以及隱藏軟鍵盤時(shí)使用0作為flags總是能夠隱藏軟鍵盤

結(jié)論

顯示軟鍵盤最可靠的方法如下:

view必須是VISIBLE的EditText栈雳,如果不是VISIBLE的,需要先將其設(shè)置為VISIBLE缔莲。 當(dāng)前界面必須已經(jīng)加載完成哥纫,不能直接在Activity的onCreate(),onResume()痴奏,onAttachedToWindow()中使用蛀骇,可以在這些方法中通過(guò)postDelayed的方式來(lái)延遲執(zhí)行showSoftInput()

隱藏軟鍵盤最方便的方法如下:

view可以當(dāng)前布局中已經(jīng)存在的任何一個(gè)View,如果找不到可以用getWindow().getDecorView()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末读拆,一起剝皮案震驚了整個(gè)濱河市擅憔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌檐晕,老刑警劉巖暑诸,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異辟灰,居然都是意外死亡个榕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門芥喇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)西采,“玉大人,你說(shuō)我怎么就攤上這事乃坤】寥茫” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵湿诊,是天一觀的道長(zhǎng)狱杰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)厅须,這世上最難降的妖魔是什么仿畸? 我笑而不...
    開(kāi)封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上错沽,老公的妹妹穿的比我還像新娘簿晓。我一直安慰自己,他們只是感情好千埃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布憔儿。 她就那樣靜靜地躺著,像睡著了一般放可。 火紅的嫁衣襯著肌膚如雪谒臼。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天耀里,我揣著相機(jī)與錄音蜈缤,去河邊找鬼。 笑死冯挎,一個(gè)胖子當(dāng)著我的面吹牛底哥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播房官,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼趾徽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了易阳?” 一聲冷哼從身側(cè)響起附较,我...
    開(kāi)封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎潦俺,沒(méi)想到半個(gè)月后拒课,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡事示,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年早像,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肖爵。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卢鹦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出劝堪,到底是詐尸還是另有隱情冀自,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布秒啦,位于F島的核電站熬粗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏余境。R本人自食惡果不足惜驻呐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一灌诅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧含末,春花似錦猜拾、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至沼撕,卻和暖如春宋雏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背务豺。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嗦明,地道東北人笼沥。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像娶牌,于是被迫代替她去往敵國(guó)和親奔浅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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