近期在項(xiàng)目中遇到了,Android軟鍵盤相關(guān)的內(nèi)容困擾了好久,也在這里記錄一下,方便查閱:
軟鍵盤的顯示調(diào)整(WindowSoftInputMode)
該屬性有如下圖的值,影響兩個(gè)方面:
1,當(dāng)Activity成為用戶注意的焦點(diǎn)時(shí)軟鍵盤的狀態(tài)(隱藏or可見)。
2,軟鍵盤彈出的時(shí)候,主窗口是否進(jìn)行調(diào)整。

以上屬性,分為state和adjust兩種(一般使用的時(shí)候也是
stateXXX | adjustXXX混合使用):
state控制軟鍵盤,顯示 or 隱藏
stateUnspecified:不指定軟鍵盤的狀態(tài)(隱藏or顯示),該屬性將由系統(tǒng)自行選擇(也是默認(rèn)的狀態(tài))。
stateUnchanged:保留狀態(tài)。當(dāng)activity發(fā)生變化的時(shí)候,保留軟鍵盤最后的狀態(tài),無論是可見or隱藏。
stateHidden:隱藏軟鍵盤,當(dāng)用戶設(shè)置了該屬性,不管是否界面有輸入需求,鍵盤都不顯示??梢栽O(shè)置該屬性,控制剛進(jìn)入界面的時(shí)候,軟鍵盤不彈出。
stateAlwaysHidden:始終隱藏軟鍵盤。
stateVisible:顯示軟鍵盤,正常的情況下軟鍵盤可以彈出,即使界面沒有輸入框的情況下,也可以強(qiáng)制彈出。
stateAlwaysVisible:總是顯示軟鍵盤。如果當(dāng)前activity設(shè)置為該屬性,那么只要返回到該activity,軟鍵盤就會(huì)彈出。區(qū)別一下stateVisible如果設(shè)置的是這個(gè)屬性切換回activity軟鍵盤不會(huì)總是彈出。
adjust在軟鍵盤彈出的時(shí)候,是否需要對(duì)activity進(jìn)行調(diào)整
adjustUnspecified:默認(rèn)屬性。讓系統(tǒng)自行選擇。
adjustResize:始終調(diào)整activity的窗口尺寸,來為軟鍵盤騰出空間。
adjustPan:不調(diào)整Activity 主窗口的尺寸來為軟鍵盤騰出空間,而是自動(dòng)平移窗口的內(nèi)容,以使焦點(diǎn)不被覆蓋,用戶始終可以看到輸入的內(nèi)容
adjustNothing:軟鍵盤彈出的時(shí)候,activity界面不做任何響應(yīng)。
舉例說明
常用的adjust為:
- adjustPan:軟鍵盤彈出,主窗口平移(TranslateY),來適應(yīng)軟鍵盤的顯示。
- adjustResize:當(dāng)軟鍵盤彈出的時(shí)候,會(huì)讓布局重新繪制,這種一般適應(yīng)于帶有滑動(dòng)的控制(比如:scrollview中有好多個(gè)EditText,當(dāng)?shù)谝粋€(gè)獲取焦點(diǎn)的時(shí)候,仍可以滑動(dòng)到最后一個(gè)EditText)。
看了好多博客,都說該屬性設(shè)置的時(shí)候,跟控件是否滑動(dòng)有區(qū)別,自己也寫了個(gè)demo測試了一下,見下面的gif圖:

-
adjustResize
可以從上圖看出,當(dāng)mode為adjustResize的時(shí)候,可以滑動(dòng)的列表(上圖左側(cè)),會(huì)調(diào)整布局,使得EditText顯示到軟鍵盤之上,并且可以滑動(dòng)。
不可滑動(dòng)的界面,如果點(diǎn)擊下方的EditText,軟鍵盤彈出就會(huì)被遮蓋。

-adjustPan
從上圖可以看出,mode為adjuetPan的時(shí)候,可滑動(dòng)列表無法顯示當(dāng)前獲取焦點(diǎn)的EditText以下的內(nèi)容(例如點(diǎn)擊可以滑動(dòng)的EditText_7,無法下拉看到下面的內(nèi)容),也就是用戶始終可以看到輸入的內(nèi)容。
不可滑動(dòng)的EditText,也是如此,會(huì)將布局向上推,以達(dá)到用戶可以始終看到的目的。
監(jiān)聽軟鍵盤是否彈出
在項(xiàng)目中有一個(gè)需求,就是不能讓軟鍵盤覆蓋輸入的內(nèi)容。使用以上windowSoftInputMode
實(shí)現(xiàn)的方式:
1,獲取decorView的高度,跟當(dāng)前內(nèi)容的高度比較,如果不一致,就說明軟鍵盤彈出:
/**
* 判斷是否軟鍵盤彈出
* @return
*/
private boolean isSoftShowing() {
//獲取當(dāng)前屏幕內(nèi)容的高度(不會(huì)變)
int screenHeight = getWindow().getDecorView().getHeight();
//獲取View可見區(qū)域的bottom
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
LogUtils.d(TAG, "screenHeight = " + screenHeight + " rect.bottom = " + rect.bottom);
return screenHeight - rect.bottom != 0;
}
2,為當(dāng)前界面的布局,添加一個(gè)onLayoutChange的接口,并將判斷邏輯添加到里面,例如:
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
boolean isShowKeyBoard = isSoftShowing();
LogUtils.d(TAG, "軟鍵盤是否彈出 : " + isShowKeyBoard);
if (isShowKeyBoard) {
mLoginLl.setTranslationY(-100);
} else if (!isShowKeyBoard) {
mLoginLl.setTranslationY(0);
}
}