在谷歌的Material Design中,文本輸入是這樣表現的:當用戶點擊輸入框想要輸入文字時,若是輸入框是空的,那麼它的提示文字(hint)就會變小而且同時移動到輸入框的上方;若是文字不爲空,則上方一直浮着這個提示文字(見https://material.google.com/components/text-fields.html#text-fields-input )。而且在I/O大會的視頻上,咱們能夠看到整個的動畫過程很優美流暢。在design support library中,TextInputLayout就是提供了它的實現。css
經過TextInputLayout來實現上述這種效果很簡單,就是在佈局代碼中每個EditText外面再套上一個TextInputLayout就能夠了,代碼以下。注意一個TextInputLayout只能套一個EditText,不然會拋異常。html
<android.support.design.widget.TextInputLayout android:id="@+id/mobile_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/image_title">
<EditText android:id="@+id/mobile" style="@style/InputEditText.Login" android:drawableLeft="@drawable/icon_small_phone" android:hint="@string/hint_mobile" android:inputType="number" android:maxLength="11"/>
</android.support.design.widget.TextInputLayout>
編譯運行,效果出現。
java
除了顯示提示文字,TextInputLayout還提供了顯示錯誤消息的接口。顯示的方法也很簡單,之前咱們是經過TextView的setError(String)
來顯示,如今改成調用TextInputLayout的setError(String)
就能夠了。代碼以下:android
ViewParent parent = editText.getParent();
if (parent instanceof TextInputLayout) {
((TextInputLayout)parent).setError(message);
}
editText.setError(message);
錯誤消息會直接顯示在編輯框下面,而且不像EditText那樣必需要得到焦點才能顯示出來。如圖所示:
markdown
除了顯示錯誤消息以外,咱們還須要清空錯誤消息,畢竟不能在用戶改正以後還一直顯示它吧。清空錯誤消息很簡單,只須要調用它的API inputLayout.setErrorEnabled(false);
便可。好比咱們能夠在用戶修改EditText時調用它:app
ViewParent viewParent = inputText.getParent();
if (viewParent != null && viewParent instanceof TextInputLayout) {
final TextInputLayout inputLayout = (TextInputLayout) viewParent;
inputText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
inputLayout.setErrorEnabled(false);
}
});
}
TextInputLayout還封裝了輸入框的輸入字數的統計。這一特性在一些字數受限的功能中但是大有用處,好比發個微博提交個用戶反饋,一般都會限定一個最大字數,於是須要顯示給用戶已經輸入了多少個字。
統計字數默認是不開啓的,咱們能夠在屬性裏配置:ide
<android.support.design.widget.TextInputLayout android:id="@+id/password_layout" app:counterEnabled="true" app:counterTextAppearance="@style/counter" app:counterMaxLength="8" app:counterOverflowTextAppearance="@style/counterOverflow" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/mobile_layout" android:layout_marginBottom="@dimen/margin_double">
counterOverflow
定義:佈局
<style name="counterOverflow"> <item name="android:textColor">@color/red</item> </style>
咱們能夠只配置counterEnabled
,這樣的話它就只會顯示輸入的字數。而counterTextAppearance
屬性則用於配置計數文本外觀。counterMaxLength
用於配置最大字數,當配置了它時,就必須再配置counterOverflowTextAppearance
,不然當用戶輸入的字數超過這個最大字數時會引起異常。
下圖是咱們配置後的運行效果:
動畫
其餘屬性與方法請參數API文檔,這裏再也不贅述。google
在上一節中,咱們能夠看到TextInputLayout與EditText在搭配使用當中,對於所需的功能都處理得很是好,那麼,爲何還要有TextInputEditText呢?
緣由很簡單,TextInputEditText是爲了填坑的。
當咱們的界面處於橫屏時,點擊一個EditText,默認狀況下不是在它下面彈出鍵盤,而是進入到輸入法的一個全屏的輸入界面(經過配置android:imeOptions="flagNoExtractUi"
能夠設爲直接在當前界面顯示)。
通常在咱們要彈出輸入法時,它會與對應的View創建一個鏈接,用於二者之間的互動,好比獲取輸入提示hint
,而後在剛纔所述的狀況中顯示到輸入法的輸入界面上。可是當咱們爲EditText外面套上一個TextInputLayout時,TextInputLayout會拿到EditText的hint
顯示出來並把EditText自己的hint
設爲空。這樣若是跳到輸入法的輸入界面上,就顯示不了咱們所設置的提示文本了。因此TextInputEditText重寫了EditText的onCreateInputConnection(EditorInfo outAttrs)
方法,把父容器的hint
內容傳給EditorInfo
,下面就是它惟一作的事情:
@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及TextInputEditText的運行效果: