Android上有很多輸入法應用,每種輸入法都有各自的特點,輸入法多數時候是和EditText配合使用,結合我自己的親身實踐分享一下使用EditText過程中遇到的一些問題及解決方法。
設定預設輸入法
有時候為了提高使用者體驗,在彈出輸入法時需要設定預設的輸入狀態,比如單詞應用彈出輸入法時,輸入法最好是在英文輸入狀態下。如果是字典應用,彈出輸入法時最好是在中文輸入狀態下,Android並沒有提供設定預設的輸入狀態的介面,但我們可以通過如下方法一樣能夠達到想要的效果:
預設中文:
1 |
mEditText.setInputType(EditorInfo.TYPE_CLASS_TEXT); |
預設英文:
1 |
mEditText.setInputType(EditorInfo.TYPE_TEXT_VARIATION_URI); |
開啟和關閉輸入法
手動控制輸入法的開關狀態也能提升使用者體驗,比如:
- 有的搜尋框會有一個清除按鈕,點選清除按鈕時就應該彈出輸入法,因為使用者清除搜尋內容的目的多數時候是需要輸入新的內容;
- 執行搜尋時應該隱藏輸入法,因為顯示輸入法時會遮擋搜尋結果,使用者體驗不太好;
- 鬧鐘來時或者有其它window彈出時應該隱藏輸入法,因為輸入法也是window,如果不隱藏可能導致輸入法遮擋住了其它window等使用者體驗不太友好的問題。
開啟輸入法:
1 2 3 4 |
private void open(Context context, View editText){ InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.showSoftInput(editText, 0); } |
關閉輸入法:
1 2 3 4 |
private void close(Context context, View editText){ InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(editText.getWindowToken(), 0); } |
監聽EditText的輸入狀態
- 類似新浪微博,在輸入內容時會提示還可以輸入多少字;
- 有的搜尋引擎,輸入內容時實時顯示搜尋結果;
- 有的輸入框有輸入長度限制,輸入內容超過長度限制時彈出提示資訊。
上面這些都可以通過監聽EditText的輸入狀態來實現,具體實現方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
mInputEditTxt.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { System.out.println("監聽EditText輸入內容的變化,在這裡可以監聽輸入內容的長度。"); } @Override public void afterTextChanged(Editable s) { System.out.println("這裡可以實現所輸即所得,使用者輸入的同時可以立即在這裡根據輸入內容執行操作,顯示搜尋結果!"); } }); |
監聽輸入法中的回車按鈕
比如搜狗輸入法的右下角有一個回車按鈕,我們希望使用者點選它時也執行確認功能,可以通過監聽EditText的按鍵點選事件來實現:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** * 監聽輸入法按鍵 * * */ mInputEditTxt.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) { System.out.println("手指彈起時執行確認功能"); return true; } return false; } }); |
改變輸入法中回車按鈕的顯示內容
如果回車按鈕是執行搜尋功能,則回車按鈕上顯示”搜尋”,如果是執行傳送功能,則顯示”傳送”,如果是下一步,則顯示”下一步”。
實現這個功能需要呼叫EditText的setImeOptions方法:
1 2 3 4 5 6 7 8 |
/** * * IME_ACTION_SEARCH 搜尋 * IME_ACTION_SEND 傳送 * IME_ACTION_NEXT 下一步 * IME_ACTION_DONE 完成 */ mInputEditTxt.setImeOptions(EditorInfo.IME_ACTION_SEARCH); |
限制輸入內容
有時候我們根本就不想使用者輸入一些雜七雜八的內容,因為這需要程式針對輸入的內容做各種處理,如果處理不當還會有好多不可預見的問題,索性在輸入內容時就禁止使用者輸入一些非法字元,這可以通過下面的方式實現,新建一個類InputTxtFilter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
public class InputTxtFilter{ public static final int INPUT_TYPE_EN = 0x01; public static final int INPUT_TYPE_CH = 0x02; private static final String[] SPELL = new String[]{ "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z", "ā","á","ǎ","à","ō","ó","ǒ","ò","ē","é","ě","è","ī","í","ǐ","ì","ū","ú","ǔ","ù","ǖ","ǘ","ǚ","ǜ","ü" }; private static char[] chineseParam = new char[]{'」',',','。','?','…',':','~','【','#','、','%','*','&','$','(','‘','’','“','”','『','〔','{','【' ,'¥','£','‖','〖','《','「','》','〗','】','}','〕','』','”',')','!',';','—'}; private InputTxtFilter( ){ } public static void inputFilter( final Context context, final EditText editText, final int type, final int inputLimit){ InputFilter[] filters = new InputFilter[1]; filters[0] = new InputFilter.LengthFilter(inputLimit){ public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend){ boolean isRightCharater = false; if(type == INPUT_TYPE_EN){ isRightCharater = isLetter(source.toString()); }else if(type == INPUT_TYPE_CH){ isRightCharater = isChineseWord(source.toString()); } if ( !isRightCharater|| dest.toString( ).length( )>=inputLimit ){ return ""; } return source; } }; editText.setFilters(filters); } /** * 檢測String是否全是中文 * */ public static boolean isChineseWord( String name ){ boolean res=true; char[] cTemp = name.toCharArray( ); for( int i = 0; i < name.length( ); i++ ){ if( !isChinese( cTemp[ i ] ) ){ res=false; break; } } return res; } /** * 是否為英文字母 * * */ public static boolean isLetter( String inputStr ){ char[] inputArray = inputStr.toCharArray( ); List<String> spellList = Arrays.asList( SPELL ); for( char input : inputArray ){ if( !spellList.contains( input + "" ) ){ return false; } } return true; } /** * 判定輸入漢字 * @param c */ public static boolean isChinese( char c ){ for( char param : chineseParam ){ if( param == c ){ return false; } } Character.UnicodeBlock ub = Character.UnicodeBlock.of( c ); if ( ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS ){ return true; } return false; } } |
在初始化EditText時,呼叫InputTxtFilter的inputFilter方法,傳入輸入長度限制、輸入內容的型別限制等即可,eg:
1 |
InputTxtFilter.inputFilter(this, mInputEditTxt, InputTxtFilter.INPUT_TYPE_EN, 5); |
遮蔽EditText的複製、貼上功能
在低版本的Android SDK中,如果對EditText的輸入長度有限制時,長按EditText並將選中的內容拖動到EditText輸入框中,如果這時候的長度超過了EditText的輸入長度限制,程式會直接崩潰掉,在高版本的Android SDK中這個問題已經改了,如果出現上面的情況會直接清空輸入框中的內容,為了避免這種討厭的問題,我們可以遮蔽EditText的複製和貼上功能,只需要遮蔽EditText的長按響應即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/** * 遮蔽複製、貼上功能 * * */ mInputEditTxt.setCustomSelectionActionModeCallback(new ActionMode.Callback() { public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { return false; } public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return false; } public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { } }); mInputEditTxt.setLongClickable(false); |