Android TextInputLayout,打造 Material Design 風格的文本輸入框

liqin5360 8年前發布 | 19K 次閱讀 Android開發 移動開發 Material Design

Android Material Design 對 EditText 輸入框的交互設計定義了一個規范,android.support.design 包中恰好提供了一個實現這些設計細節的新控件:TextInputLayout,本文就來細細分析一下。

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>

相比傳統單獨使用 EditText 的做法,新增的容器 TextInputLayout 擁有的一些獨特屬性能夠實現如下功能:

  1. hint 提示:輸入框獲取焦點時,EditText 通過 hint 屬性設置的字符串內容將浮動顯示在輸入框左上方。用戶進行輸入操作時依舊能夠看到提示信息。

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

  3. character counter:通過 counterEnabled 和 counterMaxLength 屬性可以統計輸入內容的字數,并顯示在輸入框右下角。

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

這里我寫了一個測試 Demo,layout 文件內容如下:

<?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="請輸入手機號"/>

    </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 中均有所體現。再補充幾個值得注意的地方:

  1. 浮動 hint 、error 提示、字數提示和 EditText 的背景樣式默認使用主題 style 中的 colorAccent 屬性定義的顏色;

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

  3. 控制密碼顯示狀態的切換按鈕的圖標默認呈黑色眼睛狀,TextInputLayout 提供了一些屬性供開發人員自由設置其顏色與形狀。比如「Nick Butcher」大神在他的項目 plaid 中利用 path 給圖標做出了一個很炫酷的切換動畫效果,再加上文字和小黑點的切換效果,簡直完美,如下圖所示 :

TextInputEditText

默認情況下,當設備處于橫屏時,點擊 EditText 輸入框,會彈出一個新的輸入界面并顯示軟鍵盤,即 「extract mode」(全屏模式),而不是在當前界面彈出軟鍵盤。如果單獨使用 EditText,進入「extract mode」并且在用戶還沒輸入任何內容時,hint 信息會顯示在輸入框中。但是 EditText 和 TextInputLayout 一起使用時,hint 信息則不會顯示。而 TextInputEditText 的出現剛好解決了這個問題。

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" 屬性即可。

特殊說明:經測試發現,在目前最新版本 25.0.0 的 design 包中,TextInputLayout 與 TextInputEditText 的組合使用不能實現「extract mode」顯示 hint 功能,而在舊版本中能夠實現,比如 24.1.1 版本。目測這是新版 Design 包的一個 Bug,期待下個版本的修復吧。

 

來自:http://yifeng.studio/2016/11/28/android-textinputlayout/

 

 本文由用戶 liqin5360 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!