目錄
前言
最近做項目遇到一個比較坑的難點問題。需求是在結算頁面中,有個金額輸入框,不管用戶輸入什麼數字,都保留2位小數並在輸入框中顯示出來。如下圖:
首先,我們知道EditText可以通過設置 android:inputType="numberDecimal" 軟鍵盤爲帶小數點的數字。還有,通過對EditText添加文本改變監聽事件TextWatcher,在文本改變後會回調afterTextChanged(),在這個方法中對EditText的值進行類型轉換並通過 String.format("%.2f", value) ,保留2位。 這樣實現行不行呢?
答案,肯定不行。因爲,文本只要變化就強制保留2位,會遇到一個問題,就是小數位輸入體驗極差。比如,先輸如 “1”, 這時文本轉換後顯示“1.00” ,再想輸入小數位是不是得進行刪除一個“0”,但是一旦刪除就會觸發文本改變的監聽事件,就又強制顯示成“1.00”,除非是讓用戶把光標移到到小數點後去寫。
那麼,我們使用失去焦點的方案行不行呢?答案,是可以的,只不過有點瑕疵。首先,給EditText設置焦點監聽setOnFocusChangeListener回調onFocusChange(view,hasFocus),然後調用clearFocus()失去焦點。但是,要想讓輸入框失去焦點就得找落腳點了,一般最好是選擇Activity的根視圖。但是想一想,用戶此時是軟鍵盤懸浮在頁面下方,肯定點擊收起軟鍵盤的按鈕,而這個按鈕的事件響應並沒開放。
一、軟鍵盤監聽原理
由於,安卓系統並沒有提供軟鍵盤彈入和彈出的方法。所以,我們需要自己自定義一個監聽軟件盤的類。大致實現原理就是監聽視圖樹中佈局或可視狀態發生改變超過一定的數值,認定軟鍵盤進行了彈出\收起事件了。
1、獲取根視圖rootView
View rootView =this.getWindow().getDecorView();
2、獲取根視圖屏幕高度
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
int currentVisibleHeight = r.height();
int rootViewVisibleHeight = visibleHeight;//拷貝一份,用於比較值的改變
3、監聽佈局樹視圖改變
rootView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
}
}
4、判斷軟鍵盤改變
這裏是比較關鍵的地方。這個的200是高度,是用來判斷軟鍵盤改變的佈局高度變化值,可以根據具體情況改變值大小。因爲,初始化時我們先將根視圖高度進行了拷貝一份用來判斷。
如果展開了,那麼當前根視圖的高度會比之前小的,這裏判斷比之前小了200以上,即爲軟鍵盤——彈出。
if (rootViewVisibleHeight - currentVisibleHeight > 200) {
rootViewVisibleHeight = visibleHeight;
//軟鍵盤——彈出
return;
}
if (currentVisibleHeight - rootViewVisibleHeight > 200) {
rootViewVisibleHeight = visibleHeight;
//軟鍵盤——收起
return;
}
二、軟鍵盤監聽代碼
1、清單文件設置configChanges
<activity android:name=".MainActivity"
android:launchMode="singleTop"
android:configChanges="keyboardHidden"
android:windowSoftInputMode="adjustPan|stateHidden"/>
2、 創建接口
public interface OnSoftKeyBoardChangeListener {
void keyBoardShow();
void keyBoardHide();
}
3、創建軟鍵盤監聽類
public class SoftKeyBoardListener {
//activity的根視圖
private View rootView;
//紀錄根視圖的顯示高度
private int rootViewVisibleHeight;
//接口回調
private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener;
private Activity context;
private SoftKeyBoardListener(Activity context){
this.context = context;
init(context);
}
private void init(Activity activity) {
rootView = activity.getWindow().getDecorView();
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
int visibleHeight = r.height();
if (rootViewVisibleHeight == 0) {
rootViewVisibleHeight = visibleHeight;
return;
}
//作軟鍵盤顯示/隱藏狀態沒有改變
if (rootViewVisibleHeight == visibleHeight) {
return;
}
if (rootViewVisibleHeight - visibleHeight > 200) {
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardShow();
}
rootViewVisibleHeight = visibleHeight;
return;
}
if (visibleHeight - rootViewVisibleHeight > 200) {
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardHide();
}
rootViewVisibleHeight = visibleHeight;
return;
}
}
});
}
private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener;
}
public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity);
softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener);
}
}
4、Activity中調用
SoftKeyBoardListener.setListener(MainActivity.this,
new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
@Override
public void keyBoardShow() {
Log.e("soufkeyboard", "鍵盤彈出");
}
@Override
public void keyBoardHide(int height) {
Log.e("soufkeyboard", "鍵盤收起");
}
}
);