首先鍵盤是什么缎罢,鍵盤其實是一個系統(tǒng)的dialog。當(dāng)她出現(xiàn)的時候肯定會對屏幕的尺寸造成影響饼问。所以屏幕會重繪什么啊篮撑,移動什么的。
特別特別重要的一點匆瓜,調(diào)用系統(tǒng)顯示鍵盤的方法時一定要先requestFocus這個editText的焦點。不然會出現(xiàn)一些怪異的事情,比如你掉了顯示鍵盤驮吱,他也不會彈出茧妒。
關(guān)于鍵盤是android的一個比較大的問題,像搜狗左冬,百度都是自己的輸入法桐筏,這些都是需要對android的InputMethodManager進行深入的研究,當(dāng)然首先肯定是看API
和INPUT_METHOD_SERVICE進行研究拇砰,由于這里只討論工程上的如何快速開發(fā)一個app梅忌,所以我等搬磚工只進行應(yīng)用上的研究。
首先來總結(jié)一下除破,android應(yīng)用中有哪些關(guān)于鍵盤的需求牧氮。
1.隨手打開一個app就會發(fā)現(xiàn)這樣的需求
點擊這個"寫評論"就會彈出一個輸入框,并且輸入法需要將這個輸入框頂上去瑰枫。是這樣的踱葛。
用戶點擊這個寫評論觸發(fā)了三個操作
1.EditText這個輸入框出現(xiàn),也就是visible光坝。
2.鍵盤彈出尸诽。
3.鍵盤將這個EditText頂上去。
一個一個的解決盯另。
第一步很簡單性含,只需要在點擊"寫評論"的時候?qū)⑦@個EditText的狀態(tài)visible即可。
第二鸳惯,彈出商蕴,我們先說說怎么彈出,這時候就涉及到了InputMethodManager”螅現(xiàn)在具體說這個究恤。
InputMethodManager,正如它的名字一樣后德,是一個鍵盤的管理者部宿,里面有一些和變量可以操作鍵盤。包括打開瓢湃,強制關(guān)閉等操作理张。具體代碼在github的demo里,注釋寫的很詳細了绵患。
第三雾叭,彈出的時候需要將這個visible的edittext頂上去,這時候設(shè)計到了一個屬性叫windowSoftInputMode落蝙。
一定要注意理解windowSoftInputMode的每一個屬性的意思织狐。
一般是state屬性和adjust屬性一起用暂幼,之間用 | 隔開。
state表示的是軟鍵盤在狀態(tài)切換移迫,比如activity跳轉(zhuǎn)旺嬉,view的重繪時候鍵盤的顯示或者隱藏。
"stateUnspecified": 默認設(shè)置厨埋,沒有什么用邪媳,依賴于theme的默認設(shè)置。
"stateUnchanged":當(dāng)這個activity出現(xiàn)時荡陷,軟鍵盤將一直保持在上一個activity里的狀態(tài)雨效,無論是隱藏還是顯示。
"stateHidden":當(dāng)跳轉(zhuǎn)一個activity的時候废赞,鍵盤是hide的徽龟。注意是跳轉(zhuǎn)而不是finish,也就說startActivity的時候當(dāng)前鍵盤hide蛹头,但是當(dāng)你finish當(dāng)前activity顿肺,鍵盤不會消失。
"stateAlwaysHidden":不管什么渣蜗,只要activity的主窗口獲得焦點屠尊,鍵盤就hide。
"stateVisible":軟鍵盤通常是可見的
"stateAlwaysVisible":上面的通常變成always耕拷。
"adjustUnspecified":默認設(shè)置讼昆,通常由系統(tǒng)自行決定是隱藏還是顯示
"adjustResize": 會重新繪制view,onSizeChanged會重新調(diào)用骚烧,注意adjustPan這個方法不會調(diào)用浸赫。
"adjustPan":設(shè)置成adjustPan的時候鍵盤會去找當(dāng)前界面的焦點,并始終焦點放在鍵盤的上方赃绊,使獲得焦點的view可見既峡。當(dāng)前窗口的內(nèi)容將自動移動以便當(dāng)前焦點從不被鍵盤覆蓋和用戶能總是看到輸入內(nèi)容的部分
adjustResize 和 adjustPan 的目的很簡單,他們兩個都是做一切的努力想要為這個帶有焦點的editText留出空間碧查,讓他出現(xiàn)运敢,adjustPan采用的是一種平移屏幕的方式,將editText放在鍵盤上忠售,adjustResize采用的是壓縮屏幕的方式留出空間传惠。為了留出空間,用心良苦啊稻扬。
其實布局頂起的正確與否卦方,與一下因素有關(guān):
當(dāng)一個activity繼承自Activity的時候:
非全屏模式下,一切正常泰佳。
全屏模式下盼砍,不管你是adjustXXX尘吗,最后的效果都是adjustPan。AndroidBug5497Workaround
非全屏模式一律不要加AndroidBug5497Workaround
當(dāng)一個activity繼承自AppCompatActivity的時候:
非全屏模式下浇坐,一切正常摇予。
全屏模式下,也都是adjustPan效果吗跋。但是加了AndroidBug5497Workaround就可以實現(xiàn)adjustResize。但是測量的結(jié)果可能會有偏差宁昭。
這里要注意幾點:(如下這張圖片就是下面所講的內(nèi)容布局跌宛,寫評論就是那個editText)
1.adjustResize的時候,系統(tǒng)會重新計算布局积仗,onMeasure疆拘,onSizeChanged,onLayout都會重新執(zhí)行寂曹,和adjustPan的區(qū)別方法是onSizeChanged會執(zhí)行哎迄。
需要彈出的editText輸入框不管怎么樣都要放到原始布局的最下方。內(nèi)容布局最好用ScrollView來包裹隆圆,這時候即使彈出也不會對內(nèi)容布局造成任何影響漱挚。如果用別的布局代替ScrollView的話,內(nèi)容布局就會按比例的壓縮到一起渺氧,效果不好旨涝。原因是該Activity總是調(diào)整屏幕的大小以便留出軟鍵盤的空間
2.一個怪異的問題是,當(dāng)這個editText的background只有color侣背,那么adjustResize不會有問題白华,但是adjustPan的時候,會遮擋住editText下部的一小部分贩耐,但是當(dāng)這個background是一張.9圖的時候顯示正常弧腥,我猜想,當(dāng)時介紹adjustPan的時候說了潮太,他只是努力將移動以便當(dāng)前焦點從不被鍵盤覆蓋和用戶能總是看到輸入內(nèi)容的部分管搪,他想著我你看到哪個光標(biāo)也就是焦點了吧,那好我不移了消别。
目前來說抛蚤,鍵盤還有幾個問題沒有得到優(yōu)化,后續(xù)會繼續(xù)進行寻狂。
1.全屏與adjustResize之間的沖突岁经,設(shè)置了全屏之后自己變?yōu)閍djustPan的效果了。(已解決蛇券,上面的內(nèi)容里有)
2.底部有虛擬鍵盤的情況
3.沉浸式狀態(tài)欄
2和3提到的問題缀壤,如果處理不了其實就是對于android的沉浸式樊拓,透明Navagation,還有android的window的view組成掌握的不熟悉塘慕,對AndroidBug5497Workaround不熟悉筋夏。。請到下幾篇文章(詳解AndroidBug5497Workaround图呢,android的深層布局結(jié)構(gòu))里搞一搞条篷,自己懂了原理自然就懂了。
4.鍵盤出現(xiàn)的時候布局閃動的問題蛤织,下一篇文章里會講赴叹。具體的原理依據(jù)以下源碼。
https://github.com/Jacksgong/JKeyboardPanelSwitch