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)如下功能:
hint 提示:輸入框獲取焦點(diǎn)時辕坝,EditText 通過 hint 屬性設(shè)置的字符串內(nèi)容將浮動顯示在輸入框左上方。用戶進(jìn)行輸入操作時依舊能夠看到提示信息荐健。
error 提示:通常用戶輸入的內(nèi)容需要經(jīng)過驗證酱畅,可以使用
TextInputLayout
類提供的setErrorEnabled(boolean)
和setError(CharSequence)
方法控制輸入框左下方錯誤信息的顯示與隱藏。character counter:通過
counterEnabled
和counterMaxLength
屬性可以統(tǒng)計輸入內(nèi)容的字?jǐn)?shù)江场,并顯示在輸入框右下角纺酸。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ǔ)充幾個值得注意的地方:
浮動 hint 樊诺、error 提示、字?jǐn)?shù)提示和 EditText 的背景樣式默認(rèn)使用主題 style 中的
colorAccent
屬性定義的顏色音同;使用
TextInputLayout
時词爬,設(shè)置 EditText 的 drawable 圖標(biāo)時需要同時使用相對值 (start/end) 和 絕對值 (left/right),否則 drawable 存在顯示兼容問題权均。控制密碼顯示狀態(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药蜻。