Android-EditText 樣式&軟鍵盤&輸入限制開發(fā)細(xì)節(jié)匯總

開發(fā)小日常

測試:能不能別一打開頁面毛甲,就彈出輸入鍵盤奋单?
博主:好的,我看下,這點(diǎn)疏忽了瘸洛。

測試:能不能別一打開頁面揍移,就顯示光標(biāo)?這個可以不用替用戶決定順序
博主:好的

測試:你看這個光標(biāo)是不是有點(diǎn)粗反肋?能調(diào)色嗎那伐?
博主:嗯,可以石蔗。

測試:為啥退出這個頁面后喧锦,這個軟鍵盤還在的?
博主:真的嗎抓督?來我看看燃少。

測試:這個可以讓它只輸入數(shù)字嗎?
測試:這個可以讓它只能輸入字母嗎铃在?
測試:這個可以讓它只能輸入字母和數(shù)字嗎阵具?
測試:可以讓用戶只能輸入兩位小數(shù)嗎碍遍?
測試:這個是手機(jī)號,可以限制最多 11 位嗎阳液?
博主:.....

以上是一個真實(shí)的故事怕敬,感受最深刻的就是,就一個編輯框 帘皿,細(xì)節(jié)真的不少东跪,撇去導(dǎo)致這個問題的其他因素,今天的博客是一篇以 EditText 為主題 鹰溜,記錄修改能滿足以上各種需求的干貨文章虽填。

EditText 相關(guān)知識點(diǎn)梳理

首先做個大概的了解,EditText 作為一個編輯框曹动,UI考慮上可分為以下幾點(diǎn):

  • 編輯框本身的樣式斋日。例如背景和光標(biāo),字體顏色大小等墓陈。
  • 軟鍵盤恶守。例如彈出或關(guān)閉,顯示搜索或確定贡必。
  • 輸入限制兔港。例如限制輸入字母或者數(shù)字。

EditText 的樣式

這個在寫 xml 布局文件的階段會涉及到仔拟,Android 系統(tǒng)原生的編輯框押框,丑到開發(fā)者自己都看不下去,雖然在 Material Design 風(fēng)格出來之后好了很多理逊,但是實(shí)際的項(xiàng)目開發(fā)中橡伞,Android 要和 iOS 保持統(tǒng)一,所以還是要自定義晋被。

一般情況下是這種

image

和這種

image

以及等等兑徘。

設(shè)置字體顏色大小基本使用,我就不拿出來侮辱大家智商了羡洛,來點(diǎn)實(shí)際的:

EditText 背景
通過設(shè)置 android:background 完成挂脑。

不需要背景,設(shè)置android:background=“@null”
需要特殊的背景話欲侮,就可以通過這個設(shè)置啦崭闲。

EditText 內(nèi)置的小圖標(biāo)
例如上圖左邊的放大鏡小圖標(biāo)那種,可以通過 android:drawableLeft 設(shè)置小圖標(biāo), android:drawablePadding設(shè)置小圖標(biāo)和輸入字體的間距威蕉。

需要注意的是通過這種方式添加的小圖標(biāo)刁俭,大小是沒法明確設(shè)置的,如果有額外要求韧涨,還是專門使用一個控件吧牍戚。

EditText 的光標(biāo)

EditText 的光標(biāo)顏色默認(rèn)是 colorAccent 的顏色侮繁, colorAccent不僅僅代表到光標(biāo)的顏色,還有項(xiàng)目中很多原生控件激活選擇時的顏色如孝,所以 UI 上如果對編輯框光標(biāo)顏色有需求宪哩,無法直接修改 colorAccent ,或者認(rèn)為光標(biāo)太粗了第晰,想改細(xì)一點(diǎn)锁孟,這類情況都需要設(shè)置光標(biāo)的樣式。

例如設(shè)置光標(biāo)為藍(lán)色茁瘦,寬度為 1 dp,需要先寫一個光標(biāo)樣式文件:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size android:width="1dp" />
    <solid android:color="#217aff" />
</shape>

然后通過 android:textCursorDrawable 引入這個光標(biāo)樣式品抽。

android:textCursorDrawable="@drawable/edit_cursor_color"

另外:

android:cursorVisible 改變光標(biāo)的可見性
setSelection()可以改變光標(biāo)的位置。

關(guān)于軟鍵盤

編輯框和軟鍵盤的密不可分腹躁,如果不做任何設(shè)置,頁面上EditText 會默認(rèn)搶占焦點(diǎn)南蓬,彈出軟鍵盤纺非。有的頁面是這個需求,有的則不是赘方,按需選擇烧颖。

EditText 不顯示光標(biāo),只有在點(diǎn)擊時才彈出軟鍵盤

這個在 xml 布局中給 EditText 的父布局設(shè)置觸摸獲取焦點(diǎn)可以解決,設(shè)置屬性是 android:focusableInTouchMode="true"窄陡。

示例:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:focusableInTouchMode="true" >
    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
</LinearLayout>

經(jīng)驗(yàn)證炕淮,這個屬性,并非只有在設(shè)置直接父級布局上有效跳夭,在間接父級布局上也可以涂圆。但是設(shè)置在 ScrollView 父級布局上無效。

軟鍵盤在頁面退出時币叹,不自動關(guān)閉

這個情況是润歉,最近發(fā)現(xiàn)的一個很搞笑的現(xiàn)象。頁面跳轉(zhuǎn)路徑是 A->B 颈抚,B中有 EditText踩衩,在彈出軟鍵盤后,不通過手機(jī)自帶的返回鍵贩汉,而是按 B 頁面中的返回按鈕回到 A 時驱富,發(fā)現(xiàn)軟鍵盤并未隨著B頁面自動關(guān)閉。

原因是 A 頁面設(shè)置了 android:windowSoftInputMode 設(shè)置了 stateHidden屬性匹舞。

<activity
            android:name="xxxxxxx"
            android:windowSoftInputMode="adjustPan|stateHidden"/>

解決方法是修改A頁面的 windowSoftInputMode 設(shè)置,一下是一個良心網(wǎng)友@zhangziki自測出來的表格褐鸥,大家自己設(shè)置。

windowSoftInputMode 鍵盤是否自動收回
默認(rèn)不指定
stateUnspecified
stateAlwaysVisible
stateUnchanged ×
stateHidden ×
stateAlwaysHidden ×
stateVisible ×
stateHidden ×
stateHidden ×

設(shè)置軟鍵盤的 enter 鍵

默認(rèn)的鍵盤的 enter 是換行鍵赐稽,如下:

image

但是有的時候晶疼,產(chǎn)品需求會要求酒贬,鍵盤的 enter 鍵改為其他文字,最常見的是搜索翠霍,點(diǎn)擊搜索后出發(fā)代碼中設(shè)置的搜索邏輯锭吨。

image

通過在設(shè)置 EditText 的 imeOptions 可以改變 enter 鍵的文案,要著重說明的是,因?yàn)閷⒛J(rèn)的換行鍵換為了搜索鍵寒匙,所以等于放棄了換行功能零如,所以需要通知設(shè)置 android:singleLine="true" 才能使 android:imeOptions="actionSearch" 生效。

<EditText
          android:id="@+id/editText"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:singleLine="true"
          android:imeOptions="actionSearch"/>

代碼中可以通過這個方法設(shè)置監(jiān)聽:

mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                switch (actionId) {
                    case EditorInfo.IME_ACTION_SEARCH://按下搜索鍵
                        break;
                    default:
                        break;
                }
                return false;
            }
        });

除了設(shè)置搜索按鈕之外锄弱,還有很多選項(xiàng) actionGo,actionSend,actionNext等考蕾,具體的效果,可以自己試試看会宪,道理都是一樣的肖卧。

EditText 輸入限制

inputType 設(shè)置輸入類型,例如只能輸入數(shù)字,或者輸入密碼

inputType 可以通過 xml 設(shè)置android:inputType屬性和代碼中 setInputType()
方法設(shè)置掸鹅。
API提供了很多種現(xiàn)成的格式供我們選擇塞帐, 而且這些格式可以自由組合。

android:inputType="numberPassword|number"

以上設(shè)置支持密文輸入巍沙,并且限制只允許輸入數(shù)字

digits 設(shè)置具體的支持字符

這個屬性也支持通過代碼和布局屬性設(shè)置葵姥,和 inputType 的不同之處在于,可以說這個屬性可以自定義具體的支持字符句携。

例如設(shè)置 EditText 只能輸入字符和數(shù)字:

android:digits="0123456789abcdefghijklmnopqrstuvwxyz"

設(shè)置 TextWather 監(jiān)測輸入內(nèi)容

TextWather 監(jiān)聽EditText的字符變化榔幸, 拿到用戶的輸入內(nèi)容,做我們想要的處理矮嫉。這個處理可以分為兩類:

  1. 作為一個輸入限制使用削咆。實(shí)現(xiàn) inputType 和 digits 兩個屬性無法實(shí)現(xiàn)的特殊的輸入限制需求,例如限制只輸入小數(shù)點(diǎn)后兩位 蠢笋。
  2. 作為一個事件監(jiān)聽使用态辛。滿足某種情況,觸發(fā)相應(yīng)的邏輯挺尿,例如當(dāng)輸入 16 位身份證號碼時自動調(diào)用接口驗(yàn)證是否真實(shí)有效奏黑。

這里給出一個限制只輸入小數(shù)點(diǎn)后兩位的例子。


//限制的位數(shù)
int digits = 2;

mEditText.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) {
             //刪除“.”后面超過2位后的數(shù)據(jù)
                    if (s.toString().contains(".")) {
                        if (s.length() - 1 - s.toString().indexOf(".") > digits) {
                            s = s.toString().subSequence(0,
                                    s.toString().indexOf(".") + digits+1);
                            editText.setText(s);
                            editText.setSelection(s.length()); //光標(biāo)移到最后
                        }
                    }
                    //如果"."在起始位置,則起始位置自動補(bǔ)0
                    if (s.toString().trim().substring(0).equals(".")) {
                        s = "0" + s;
                        editText.setText(s);
                        editText.setSelection(2);
                    }

                    //如果起始位置為0,且第二位跟的不是".",則無法后續(xù)輸入
                    if (s.toString().startsWith("0")
                            && s.toString().trim().length() > 1) {
                        if (!s.toString().substring(1, 2).equals(".")) {
                            editText.setText(s.subSequence(0, 1));
                            editText.setSelection(1);
                            return;
                        }
                    }
           }

           @Override
           public void afterTextChanged(Editable s) {

           }
       });

設(shè)置 InputFilter 過濾器

除了 TextWather编矾,自定義 InputFilter 過濾器也能達(dá)到我們特殊的過濾需求熟史。例如上面的限制兩位小數(shù)點(diǎn)后兩位。

設(shè)置 InputFilter 過濾器需要兩步:

  1. 自定義 InputFilter, 繼承一個合適的 KeyListener窄俏, 重寫filter()方法蹂匹,這里面編寫你想要的過濾限制。
  2. EditText 通過 setFilters 設(shè)置過濾器凹蜈。

在我看來限寞,如果實(shí)現(xiàn)輸入限制這類功能忍啸,InputFilter 的實(shí)現(xiàn)方式比 TextWather 顯的更加優(yōu)雅一點(diǎn),而且從方法名稱上看也是理所當(dāng)然的履植。TextWather 更適合去做監(jiān)聽類使用计雌。

下面給出限制兩位小數(shù)點(diǎn)后兩位的 InputFilter 實(shí)現(xiàn)版本。

public class MoneyValueFilter extends DigitsKeyListener {

    private static final String TAG = "MoneyValueFilter";
    public MoneyValueFilter() {
        super(false, true);
    }

    private int digits = 2;

    public MoneyValueFilter setDigits(int d) {
        digits = d;
        return this;
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end,
                               Spanned dest, int dstart, int dend) {
        CharSequence out = super.filter(source, start, end, dest, dstart, dend);


        // if changed, replace the source
        if (out != null) {
            source = out;
            start = 0;
            end = out.length();
        }

        int len = end - start;

        // if deleting, source is empty
        // and deleting can't break anything
        if (len == 0) {
            return source;
        }

        //以點(diǎn)開始的時候玫霎,自動在前面添加0
        if(source.toString().equals(".") && dstart == 0){
            return "0.";
        }
        //如果起始位置為0,且第二位跟的不是".",則無法后續(xù)輸入
        if(!source.toString().equals(".") && dest.toString().equals("0")){
            return "";
        }

        int dlen = dest.length();

        // Find the position of the decimal .
        for (int i = 0; i < dstart; i++) {
            if (dest.charAt(i) == '.') {
                // being here means, that a number has
                // been inserted after the dot
                // check if the amount of digits is right
                return (dlen-(i+1) + len > digits) ?
                    "" :
                    new SpannableStringBuilder(source, start, end);
            }
        }

        for (int i = start; i < end; ++i) {
            if (source.charAt(i) == '.') {
                // being here means, dot has been inserted
                // check if the amount of digits is right
                if ((dlen-dend) + (end-(i + 1)) > digits)
                    return "";
                else
                    break;  // return new SpannableStringBuilder(source, start, end);
            }
        }



        // if the dot is after the inserted part,
        // nothing can break
        return new SpannableStringBuilder(source, start, end);
    }
}


mEditText.setFilters(new InputFilter[]{new MoneyValueFilter().setDigits(3)});

最后

雖然都是一些小細(xì)節(jié)凿滤,也要重視起來,因?yàn)榧?xì)節(jié)決定成敗吶庶近,希望自己以后要多注意翁脆,努力降低 bug 率,F(xiàn)ighting!

另外鼻种,關(guān)于限制兩位小樹輸入的需求的代碼已上傳我的 github反番,項(xiàng)目地址為 DR_MoneyEditTextDemo,歡迎 Star,熱烈歡迎 Follow 。


歡迎關(guān)注博主的微信公眾號叉钥,快快加入哦罢缸,期待與你一起成長!
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沼侣,一起剝皮案震驚了整個濱河市祖能,隨后出現(xiàn)的幾起案子歉秫,更是在濱河造成了極大的恐慌蛾洛,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雁芙,死亡現(xiàn)場離奇詭異轧膘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)兔甘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門谎碍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洞焙,你說我怎么就攤上這事蟆淀。” “怎么了澡匪?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵熔任,是天一觀的道長。 經(jīng)常有香客問我唁情,道長疑苔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任甸鸟,我火速辦了婚禮惦费,結(jié)果婚禮上兵迅,老公的妹妹穿的比我還像新娘。我一直安慰自己薪贫,他們只是感情好恍箭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著后雷,像睡著了一般季惯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上臀突,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天勉抓,我揣著相機(jī)與錄音,去河邊找鬼候学。 笑死藕筋,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梳码。 我是一名探鬼主播隐圾,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼掰茶!你這毒婦竟也來了暇藏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤濒蒋,失蹤者是張志新(化名)和其女友劉穎盐碱,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沪伙,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瓮顽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了围橡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暖混。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖翁授,靈堂內(nèi)的尸體忽然破棺而出拣播,到底是詐尸還是另有隱情,我是刑警寧澤收擦,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布贮配,位于F島的核電站,受9級特大地震影響炬守,放射性物質(zhì)發(fā)生泄漏牧嫉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望酣藻。 院中可真熱鬧曹洽,春花似錦、人聲如沸辽剧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怕轿。三九已至偷崩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撞羽,已是汗流浹背阐斜。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诀紊,地道東北人谒出。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像邻奠,于是被迫代替她去往敵國和親笤喳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,524評論 25 707
  • 引言 EditTex是Android中比較常用的一個控件,可以說它是用戶和Android應(yīng)用進(jìn)行數(shù)據(jù)傳遞的通道.通...
    OzanShareing閱讀 6,172評論 5 33
  • 目 錄|河伯與共工 上一章|長生館(6)黃泉的真像 扶風(fēng)城北近郊有一小鎮(zhèn)平安碌宴,鎮(zhèn)上有間客棧名為長生館杀狡。菜品新奇,食...
    寧采野花不采臣閱讀 1,229評論 18 21
  • 為什么活著贰镣? 想了許久仍在原點(diǎn) 或許沒什么好想的 春冬秋夏 四季輪回 人也在這世上走了一遭 本就無奇 你不想只是為...
    胡蘿卜拐跑了小兔子閱讀 146評論 1 0