今天在項(xiàng)目中遇到了一個(gè)軟鍵盤遮擋住輸入框的特殊案例,經(jīng)過和搭檔的研究,終于完美解決了。寫下這篇文章,記錄一下,順便回顧學(xué)習(xí)windowSoftInputMode系列屬性以及軟鍵盤的相關(guān)知識(shí)。
windowSoftInputMode
下面是windowSoftInputMode的Documentation
Formats: flag
Values: adjustNothing, adjustPan, adjustResize, adjustUnspecified, stateAlwaysHidden, stateAlwaysVisible, stateHidden, stateUnchanged, stateUnspecified, stateVisible
Specify the default soft-input mode for the main window of this activity. A value besides "unspecified" here overrides any value in the theme.
我的英語知識(shí)小學(xué)級(jí)別的,哈哈……上面的大概意思呢,我認(rèn)為就是說:這是一個(gè)標(biāo)簽,它可以取的值有這么多,我們可以從中選擇設(shè)置一個(gè)值來控制當(dāng)前這個(gè)活動(dòng)窗口與軟鍵盤之間的交互。既然是交互,這時(shí)就有兩種狀態(tài),從這些values的命名也可以看出來,一種是窗口的,一種是軟鍵盤的
window: adjustNothing, adjustPan, adjustResize, adjustUnspecified
softInput:stateAlwaysHidden, stateAlwaysVisible, stateHidden, stateUnchanged, stateUnspecified, stateVisible
它的設(shè)置必須是下面列表中的一個(gè)值,或一個(gè) ”state…”值加一個(gè) ”adjust…”值的組合。
值 | 作用 |
---|---|
adjustPan | 當(dāng)顯示軟鍵盤時(shí),調(diào)整window的空白區(qū)域來顯示軟鍵盤。軟鍵盤還是有可能遮擋一些有內(nèi)容區(qū)域,這時(shí)用戶就只有退出軟鍵盤才能看到這些被遮擋區(qū)域并進(jìn)行交互。 |
adjustNothing | 當(dāng)顯示軟鍵盤時(shí),不調(diào)整window的布局 |
adjustResize | 當(dāng)顯示軟鍵盤時(shí),調(diào)整window內(nèi)的控件大小以便顯示軟鍵盤。這樣的話控件可能會(huì)變形。 |
adjustUnspecified | 不指定顯示軟件盤時(shí),window的調(diào)整方式。系統(tǒng)去判斷內(nèi)容區(qū)域可滾動(dòng)為adjustPan,不可滾動(dòng)為adjustResize |
stateAlwaysHidden | 總是隱藏軟鍵盤。 |
stateAlwaysVisible | 總是顯示軟鍵盤 |
stateHidden | 用戶導(dǎo)航(navigate)到你的窗口的時(shí)候,隱藏軟鍵盤 |
stateVisible | 用戶導(dǎo)航(navigate)到你的窗口的時(shí)候,顯示軟鍵盤 |
stateUnchanged | 當(dāng)這個(gè)activity出現(xiàn)時(shí),軟鍵盤將一直保持在上一個(gè)activity里的狀態(tài),無論是隱藏還是顯示 |
stateUnspecified | 未指定軟鍵盤的狀態(tài),系統(tǒng)將自動(dòng)選擇一個(gè)合適的狀態(tài)或依賴于主題中的設(shè)置,這是默認(rèn)的設(shè)置 |
軟鍵盤顯示和隱藏
正好前兩天用到代碼去設(shè)置軟鍵盤的彈出與隱藏,也在此記錄一下,因?yàn)轱@示與隱藏軟件盤的方式都有多種,但是有的卻是不起作用,下面是兩種親測可用的顯示與隱藏方法
/**
* 隱藏軟鍵盤
* @param view
*/
public static void hideSoftKeyboard() {
if (view == null || BaseApplication.getContext() == null)
return;
((InputMethodManager) BaseApplication.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(
view.getWindowToken(), 0);
}
/**
* 顯示軟鍵盤
*/
public static void showSoftKeyboard(){
((InputMethodManager) BaseApplication.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE)).toggleSoftInput(0, InputMethodManager.RESULT_SHOWN);
}
以上,將知識(shí)順了一遍;下面,來說說我今天是怎么爬坑的
我的布局如圖所示,在AndroidManifest中進(jìn)行設(shè)置該Activity:
-
windowSoftInputMode="adjustNothing"
這時(shí),當(dāng)軟件盤彈出時(shí),window不作調(diào)整,當(dāng)頁面向上滑動(dòng)到頂時(shí),下面有輸入框,會(huì)被軟鍵盤蓋住 -
windowSoftInputMode="adjustPan"
這時(shí),當(dāng)軟鍵盤彈出時(shí),window調(diào)整頁面顯示,這個(gè)是調(diào)整空白區(qū)域,會(huì)自動(dòng)將獲取焦點(diǎn)的輸入框滑動(dòng)到彈出的軟鍵盤上方,但是,當(dāng)最下方的輸入框,還是會(huì)被遮擋,這時(shí)window已經(jīng)調(diào)整不了,并且頁面向上滑動(dòng)時(shí),Toolbar也會(huì)被頂出屏幕 -
windowSoftInputMode="adjustResize"
- 這時(shí),當(dāng)軟鍵盤彈出時(shí),window調(diào)整頁面顯示,這個(gè)調(diào)整是調(diào)整整個(gè)頁面的大小,比如,現(xiàn)在軟鍵盤彈出,那么上面我這個(gè)頁面,等于是整體往上壓縮,下面擠出一個(gè)可以放下軟鍵盤的區(qū)域,所以,就會(huì)把我下方的LinearLayout區(qū)域都擠上去,那么整個(gè)頁面都變形了。
- 想辦法:監(jiān)聽Scrollview的布局是否改變,判斷它的bottom變大變小,將LinearLayout顯示隱藏,想法是好的,但是,軟鍵盤彈出,LinearLayout隱藏后,軟鍵盤上方總是有一塊和我布局下方LinearLayout同樣大小的灰色區(qū)域,并且,當(dāng)退出軟鍵盤后,如果用的隱藏是VIEW.GONE的話,LinearLayout就回不來了
- 查找后,發(fā)現(xiàn)灰色區(qū)域原因出在我的Scrollview的布局屬性weight=1上;至于設(shè)置成VIEW.GONE下方的LinearLayout再設(shè)置成VIEW.VISIBLE也回不來,不再顯示,不明白,只能先用VIEW.VISIBLE屬性
- 解決辦法:
- windowSoftInputMode="adjustResize"
- 根布局修改為RelativeLayout,不再用weight屬性,解決了軟鍵盤上方灰色區(qū)域問題
//添加布局改變監(jiān)聽
scrollviewActorder.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
LogUtil.ShowLog(bottom+"==="+oldBottom);
if (oldBottom>bottom) {
// 打開了軟鍵盤,觸發(fā)了界面resize
// 隱藏下方價(jià)格,按鈕
LogUtil.ShowLog("size change ----------");
llBottom.setVisibility(View.INVISIBLE);
llBottom.setFocusable(false);
}else if(bottom>oldBottom){
llBottom.setVisibility(View.VISIBLE);
llBottom.setFocusable(true);
}
}
});
經(jīng)過上面一系列的折騰,終于,將軟鍵盤遮擋住輸入框的問題完美解決。