Android TextInputLayout,打造 Material Design 風(fēng)格的文本輸入框

Android Material Design 對 EditText 輸入框的交互設(shè)計定義了一個規(guī)范卤恳,詳細(xì)設(shè)計細(xì)節(jié)可以參考官網(wǎng)介紹:Components/Text fields (需要 翻墻 )秸歧。android.support.design 包中恰好提供了一個實現(xiàn)這些設(shè)計細(xì)節(jié)的新控件:TextInputLayout灾锯,本文就來細(xì)細(xì)分析一下。

TextInputLayout


LinearLayout 的子類贞铣,專用于包裹 EditText 的一個 ViewGroup 闹啦,基本用法如下:

<android.support.design.widget.TextInputLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content">

     <android.support.design.widget.TextInputEditText
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:hint="@string/form_username"/>

 </android.support.design.widget.TextInputLayout>

相比傳統(tǒng)單獨(dú)使用 EditText 的做法,新增的容器 TextInputLayout 擁有的一些獨(dú)特屬性能夠?qū)崿F(xiàn)如下功能:

  1. hint 提示:輸入框獲取焦點(diǎn)時辕坝,EditText 通過 hint 屬性設(shè)置的字符串內(nèi)容將浮動顯示在輸入框左上方。用戶進(jìn)行輸入操作時依舊能夠看到提示信息荐健。

  2. error 提示:通常用戶輸入的內(nèi)容需要經(jīng)過驗證酱畅,可以使用 TextInputLayout 類提供的 setErrorEnabled(boolean)setError(CharSequence) 方法控制輸入框左下方錯誤信息的顯示與隱藏。

  3. character counter:通過 counterEnabledcounterMaxLength 屬性可以統(tǒng)計輸入內(nèi)容的字?jǐn)?shù)江场,并顯示在輸入框右下角纺酸。

  4. Password visibility toggling:當(dāng)輸入框內(nèi)容為密碼類信息時,可以通過 passwordToggleEnabled 屬性或者 setPasswordVisibilityToggleEnabled(boolean) 方法在輸入框右側(cè) drawableRight 的位置顯示一個切換按鈕址否,控制輸入內(nèi)容的顯示與隱藏餐蔬。

這里我寫了一個測試 Demo,layout 文件內(nèi)容如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusableInTouchMode="true"
    android:orientation="vertical">

    <include
        layout="@layout/include_toolbar"/>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/til_mobile"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_16"
        android:layout_marginLeft="@dimen/dp_16"
        android:layout_marginRight="@dimen/dp_16"
        app:counterEnabled="true"
        app:counterMaxLength="11">

        <android.support.design.widget.TextInputEditText
            android:id="@+id/et_mobile"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:drawableLeft="@mipmap/ic_mobile"
            android:drawableStart="@mipmap/ic_mobile"
            android:drawablePadding="@dimen/dp_4"
            android:gravity="center_vertical"
            android:inputType="number"
            android:hint="請輸入手機(jī)號"/>

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/til_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginRight="@dimen/dp_16"
        android:layout_marginLeft="@dimen/dp_16"
        app:passwordToggleEnabled="true">

        <android.support.design.widget.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:drawableLeft="@mipmap/ic_password"
            android:drawableStart="@mipmap/ic_password"
            android:drawablePadding="@dimen/dp_4"
            android:gravity="center_vertical"
            android:hint="請輸入密碼"
            android:inputType="textPassword"/>

    </android.support.design.widget.TextInputLayout>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/dp_16"
        android:onClick="onClickLogin"
        android:text="登錄"
        android:textColor="@color/white"
        android:textSize="@dimen/sp_16"
        android:background="@color/blue"/>

</LinearLayout>

效果如圖:

前面提到的 TextInputLayout 的四個功能在 Demo 中均有所體現(xiàn)佑附。再補(bǔ)充幾個值得注意的地方:

  1. 浮動 hint 樊诺、error 提示、字?jǐn)?shù)提示和 EditText 的背景樣式默認(rèn)使用主題 style 中的 colorAccent 屬性定義的顏色音同;

  2. 使用 TextInputLayout 時词爬,設(shè)置 EditText 的 drawable 圖標(biāo)時需要同時使用相對值 (start/end) 和 絕對值 (left/right),否則 drawable 存在顯示兼容問題权均。

  3. 控制密碼顯示狀態(tài)的切換按鈕的圖標(biāo)默認(rèn)呈黑色眼睛狀顿膨,TextInputLayout 提供了一些屬性供開發(fā)人員自由設(shè)置其顏色與形狀。比如「Nick Butcher」大神在他的項目 plaid 中利用 path 給圖標(biāo)做出了一個很炫酷的切換動畫效果叽赊,再加上文字和小黑點(diǎn)的切換效果恋沃,簡直完美,如下圖所示 (圖片源自 Twitter):

具體代碼實現(xiàn)過程必指,可以直接參考:Plaid - Animated DN password visibility toggle囊咏。

TextInputEditText


默認(rèn)情況下,當(dāng)設(shè)備處于橫屏?xí)r取劫,點(diǎn)擊 EditText 輸入框匆笤,會彈出一個新的輸入界面并顯示軟鍵盤,即 「extract mode」(全屏模式)谱邪,而不是在當(dāng)前界面彈出軟鍵盤炮捧。如果單獨(dú)使用 EditText,進(jìn)入「extract mode」并且在用戶還沒輸入任何內(nèi)容時惦银,hint 信息會顯示在輸入框中咆课。但是 EditText 和 TextInputLayout 一起使用時末誓,hint 信息則不會顯示。而 TextInputEditText 的出現(xiàn)剛好解決了這個問題书蚪。

TextInputEditText 是 AppCompatEditText (繼承自 EditText) 的子類喇澡,源碼很簡單,只是重寫 onCreateInputConnection 方法殊校,做了一個 hint 信息的傳遞晴玖,就是為了在「extract mode」中顯示 hint 信息:

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        final InputConnection ic = super.onCreateInputConnection(outAttrs);
        if (ic != null && outAttrs.hintText == null) {
            // If we don't have a hint and our parent is a TextInputLayout, use it's hint for the
            // EditorInfo. This allows us to display a hint in 'extract mode'.
            final ViewParent parent = getParent();
            if (parent instanceof TextInputLayout) {
                outAttrs.hintText = ((TextInputLayout) parent).getHint();
            }
        }
        return ic;
    }

使用時,只需要將 TextInputLayout 中的 EditText 替換成 TextInputEditText 控件即可为流,屬性和 EditText 一樣呕屎,沒有什么其他特殊用法,我們看一下效果圖敬察。

TextInputLayout 與 EditText:

TextInputLayout 與 TextInputEditText:

備注:如果不想使用 EditText 的「extract mode」秀睛,添加 android:imeOptions="flagNoExtractUi" 屬性即可。

特殊說明:經(jīng)測試發(fā)現(xiàn)莲祸,在目前最新版本 25.0.0 的 design 包中蹂安,TextInputLayout 與 TextInputEditText 的組合使用不能實現(xiàn)「extract mode」顯示 hint 功能,而在舊版本中能夠?qū)崿F(xiàn)锐帜,比如 24.1.1 版本田盈。目測這是新版 Design 包的一個 Bug,期待下個版本的修復(fù)吧抹估。

最后缠黍,附上「Android Material Design」系列文章的 Demo 地址:MDStudySamples,歡迎 Star药蜻。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瓷式,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子语泽,更是在濱河造成了極大的恐慌贸典,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踱卵,死亡現(xiàn)場離奇詭異廊驼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)惋砂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門妒挎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人西饵,你說我怎么就攤上這事酝掩。” “怎么了眷柔?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵期虾,是天一觀的道長原朝。 經(jīng)常有香客問我,道長镶苞,這世上最難降的妖魔是什么喳坠? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮茂蚓,結(jié)果婚禮上壕鹉,老公的妹妹穿的比我還像新娘。我一直安慰自己聋涨,他們只是感情好御板,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著牛郑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪敬鬓。 梳的紋絲不亂的頭發(fā)上淹朋,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音钉答,去河邊找鬼础芍。 笑死,一個胖子當(dāng)著我的面吹牛数尿,可吹牛的內(nèi)容都是我干的仑性。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼右蹦,長吁一口氣:“原來是場噩夢啊……” “哼诊杆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起何陆,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤晨汹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后贷盲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淘这,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年巩剖,在試婚紗的時候發(fā)現(xiàn)自己被綠了铝穷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡佳魔,死狀恐怖曙聂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吃引,我是刑警寧澤筹陵,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布刽锤,位于F島的核電站,受9級特大地震影響朦佩,放射性物質(zhì)發(fā)生泄漏并思。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一语稠、第九天 我趴在偏房一處隱蔽的房頂上張望宋彼。 院中可真熱鬧,春花似錦仙畦、人聲如沸输涕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莱坎。三九已至,卻和暖如春寸士,著一層夾襖步出監(jiān)牢的瞬間檐什,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工弱卡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乃正,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓婶博,卻偏偏與公主長得像瓮具,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子凡人,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

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