登錄、注冊等界面經常會出現軟鍵盤彈出遮擋登錄按鈕的情況,按界面布局的不同,可選擇不同的方案進行解決,舉例如下:
普通類型
這種類型的界面有以下特點:
- 非全屏模式
- 背景是純色而不是圖片
針對以上模式,單純設置
android:windowSoftInputMode="adjustResize"
或者在最外層加上 ScrollView都并不足以完全解決問題,有以下2種方案可選
無ScrollView,RelativeLayout+adjustResize方案
- 將layout的最外層用 RelativeLayout ,而不是ScrollView或者LinearLayout
- 將需要軟鍵盤跟隨的控件放置在RelativeLayout的底部
- 讓其他控件的位置根據這個控件來設置相對值
- android:windowSoftInputMode=“adjustResize”
無adjustResize,僅ScrollView方案
- 將需要顯示的所有內容用ScrollView包含
- 為EditText設置setOnFocusChangeListener 和 setOnTouchListener
- 使ScrollView滾動至底部
- 注意滾動時需延遲100ms~300ms(軟鍵盤彈出的時間)
核心代碼:
/**
* 使滾動條滾動至指定位置(垂直滾動)
*
* @param scrollView 要滾動的ScrollView
* @param to 滾動到的位置
*/
protected void scrollVertical(final ScrollView scrollView, final int to) {
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.scrollTo(0, to);
}
},100);
}
/**
* 使ScrollView滾動至底部,顯示Submit按鈕
*
* @param scrollView 要滾動的scrollView
*/
protected void scrollToShowSubmitBtn(final ScrollView scrollView) {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollVertical(scrollView, scrollView.getHeight());
}
}, 100);
}
全屏模式或背景為圖片的布局
- 全屏模式
全屏模式不允許對界面進行Resize,因此一旦在style中設置了
<item name="android:windowFullscreen">true</item>
則在AndroidManifest.xml中設置
android:windowSoftInputMode="adjustResize"
將無效
同理,在layout中增加ScorllView也無法解決問題。
- 背景為圖片
如果背景是圖片,無論是adjustResize還是ScrollView都將導致圖片變形
這種類型的布局,只能監聽軟鍵盤狀態,根據鍵盤狀態,調整布局,顯示登錄按鈕
需要注意的是,在不同inputType的EditText間切換時,軟鍵盤會消失再彈出,因此在調整布局時需要延遲幾百毫秒,等待軟鍵盤彈出,核心代碼如下:
public abstract class BaseActivity extends AppCompatActivity {
/**
* 判斷軟鍵盤是否打開
*
* @param rootView 最上層布局
* @return 打開:true,隱藏:false
*/
private boolean isKeyboardShown(View rootView) {
final int softKeyboardHeight = 100;
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
int heightDiff = rootView.getBottom() - r.bottom;
return heightDiff > softKeyboardHeight * dm.density;
}
/**
* 添加軟鍵盤狀態監聽器
*/
protected void setKeyboardStateListener() {
final View rootView = getWindow().getDecorView().findViewById(android.R.id.content);
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
rootView.postDelayed(new Runnable() {
@Override
public void run() {
if (isKeyboardShown(rootView)) {
onKeyBoardShow();
} else {
onKeyBoardHide();
}
}
},100);
}
});
}
/**
* 軟鍵盤打開時要做的操作
*/
protected abstract void onKeyBoardShow();
/**
* 軟鍵盤隱藏時要做的操作
*/
protected abstract void onKeyBoardHide();
}