導讀:
Android 從5.0版本開始,新增了Android Materia Design庫,讓開發者高效的實現炫酷的UI效果
本篇文章將介紹Materia Design庫的TextInputLayout與TextInputEditText組件
TextInputLayout
TextInputLayout用於輔助EditText,當用戶輸入文本時,在EditText上方顯示浮動標籤,這個標籤的內容就是我們設置的android:hint屬性.
TextInputLayout 屬於Android Design Support library,可以直接向下兼容到Android 2.2.
TextInputLayout 繼承於Linerlayout,說明它是一個佈局,需要配合子控件使用才能顯示想要的效果,類似ScrollView的用法
TextInputLayout 屬性說明
屬性 | 說明 |
---|---|
app:Theme | 設置下劃線或其他的顏色屬性 |
android.support.design:counterEnabled | 是否顯示計數器 |
android.support.design:counterMaxLength | 設置計數器的最大值,與counterEnabled同時使用 |
android.support.design:counterTextAppearance | 計數器的字體樣式 |
android.support.design:counterOverflowTextAppearance | 輸入字符大於我們限定個數字符時的字體樣式 |
android.support.design:errorEnabled | 是否顯示錯誤信息 |
android.support.design:errorTextAppearance | 錯誤信息的字體樣式 |
android.support.design:hintAnimationEnabled | 是否顯示hint的動畫,默認true |
android.support.design:hintEnabled | 是否使用hint屬性,默認true |
android.support.design:hintTextAppearance | 設置hint的文字樣式(指運行動畫效果之後的樣式) |
android.support.design:passwordToggleDrawable | 設置密碼開關Drawable圖片,於passwordToggleEnabled同時使用 |
android.support.design:passwordToggleEnabled | 是否顯示密碼開關圖片,需要EditText設置inputType |
android.support.design:passwordToggleTint | 設置密碼開關圖片顏色 |
android.support.design:passwordToggleTintMode | 設置密碼開關圖片(混合顏色模式),與passwordToggleTint同時使用 |
TextInputLayout使用
一、moudle的bulid.gradle 添加依賴庫:
dependencies {
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:26.0.0-alpha1'
}
二、XML佈局文件設置屬性
<?xml version="1.0" encoding="utf-8"?>
<!-- xmlns:app="http://schemas.android.com/apk/res-auto" 記得設置命名空間-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="xmx.zs.materia_design.TextInputLayoutActivity">
<!--android.support.design:hintAnimationEnabled | 是否顯示hint的動畫,默認true-->
<!--android.support.design:hintEnabled | 是否使用hint屬性,默認true-->
<!--android.support.design:hintTextAppearance | 設置hint的文字樣式(指運行動畫效果之後的樣式)-->
<!--android.support.design:counterEnabled | 是否顯示計數器-->
<!--android.support.design:counterMaxLength | 設置計數器的最大值-->
<!--android.support.design:counterOverflowTextAppearance | 輸入字符大於我們限定個數字符時的樣式-->
<!--app:theme 設置浮動標籤的顏色主題-->
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:counterEnabled="true"
app:counterMaxLength="5"
app:counterOverflowTextAppearance="@style/OverTextAppearance"
app:counterTextAppearance="@style/CountTextAppearance"
app:hintAnimationEnabled="false"
app:hintEnabled="true"
app:hintTextAppearance="@style/EditText_hintTextAppearance"
app:theme="@style/EditText_Theme">
<!--EditText 設置左側圖片,系統建議drawableStart/drawableLeft一起用,API>17-->
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@mipmap/edit_account"
android:drawableStart="@mipmap/edit_account"
android:hint="請輸入用戶名"
android:imeOptions="actionNext"
android:inputType="text"/>
</android.support.design.widget.TextInputLayout>
<!--android.support.design:passwordToggleEnabled | 是否顯示密碼開關圖片,需要EditText設置inputType-->
<!--android.support.design:passwordToggleTint | 設置密碼開關圖片顏色-->
<!--android.support.design:passwordToggleTintMode | 設置密碼開關圖片(混合顏色模式),與passwordToggleTint同時使用-->
<!--android.support.design:errorEnabled |是否顯示錯誤信息-->
<!--android.support.design:errorTextAppearance| 錯誤信息的字體樣式-->
<!--系統默認的密碼開關(修改顏色主題)-->
<android.support.design.widget.TextInputLayout
android:id="@+id/til"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入密碼"
app:counterEnabled="true"
app:counterMaxLength="5"
app:counterOverflowTextAppearance="@style/OverTextAppearance"
app:counterTextAppearance="@style/CountTextAppearance"
app:errorEnabled="true"
app:errorTextAppearance="@style/ErrorTextAppearance"
app:passwordToggleEnabled="true"
app:passwordToggleTint="@color/colorPrimaryDark"
app:passwordToggleTintMode="multiply"
app:theme="@style/EditText_Theme">
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@mipmap/edit_lock"
android:drawableStart="@mipmap/edit_lock"
android:imeOptions="actionNext"
android:inputType="textPassword"
android:paddingLeft="100dp"/>
</android.support.design.widget.TextInputLayout>
<!--android.support.design:passwordToggleDrawable | 設置密碼開關Drawable圖片-->
<!--自定義我們的密碼開關圖片(drawable)-->
<android.support.design.widget.TextInputLayout
android:id="@+id/til_customize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請確認密碼"
app:counterEnabled="true"
app:counterMaxLength="5"
app:passwordToggleDrawable="@drawable/password_visible_invisible"
app:passwordToggleEnabled="true"
>
<android.support.design.widget.TextInputEditText
android:id="@+id/editText_customize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@mipmap/edit_lock"
android:drawableStart="@mipmap/edit_lock"
android:imeOptions="actionDone"
android:inputType="textPassword"/>
</android.support.design.widget.TextInputLayout>
<!--Test EditText.setCompoundDrawables()-->
<android.support.design.widget.TextInputLayout
android:id="@+id/til_testEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:passwordToggleDrawable="@drawable/password_visible_invisible"
>
<EditText
android:id="@+id/editText_drawable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@mipmap/edit_lock"
android:drawableStart="@mipmap/edit_lock"
android:hint="Test EditText.setCompoundDrawables()"
android:inputType="numberPassword"/>
</android.support.design.widget.TextInputLayout>
<!--Test EditText.setCompoundDrawablesWithIntrinsicBounds()-->
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:passwordToggleDrawable="@drawable/password_visible_invisible">
<EditText
android:id="@+id/editText_drawable2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Test EditText.setCompoundDrawablesWithIntrinsicBounds()"
android:inputType="numberPassword"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
三、MainActivity中調用控件
其實做完上面兩步就已經有效果了,這裏簡單的演示下:
EditText.setError()和TextInputLayout.setError()的簡單監聽
EditText.setCompoundDrawables()和EditText.setCompoundDrawablesWithIntrinsicBounds()的簡單使用
/*
* @創建者 默小銘
* @博客 http://blog.csdn.net/u012792686
* @創建時間 2017/6/10
* @本類描述 TextInputLyout 實際使用例子
* @內容說明
* @補充內容
*
* ---------------------------------
* @更新時間
* @新增內容
*
*/
public class TextInputLayoutActivity extends AppCompatActivity {
private TextInputEditText mEditText_customize;
private TextInputLayout mTil_customize;
private EditText mEditText;
private TextInputLayout mTextInputLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text_input_layout);
//自定義密碼開關輸入框
mEditText_customize = (TextInputEditText) findViewById(R.id.editText_customize);
mTil_customize = (TextInputLayout) findViewById(R.id.til_customize);
//系統自帶的密碼開關輸入框
mEditText = (EditText) findViewById(R.id.editText);
mTextInputLayout = (TextInputLayout) findViewById(R.id.til);
testSetCompoundDrawables();
testSetCompoundDrawablesWithIntrinsicBounds();
customizeEditText();
TextInputLyout_EditText();
}
/**
* 測試EditText.setCompoundDrawablesWithIntrinsicBounds()
* <p>
* 可以在上、下、左、右設置圖標,如果不想在某個地方顯示,則設置爲null。
* <p>
* 圖標的寬高將會設置爲固有寬高,既自動通過getIntrinsicWidth和getIntrinsicHeight獲取。
* <p>
* 即:這種方式只能顯示原圖
*/
private void testSetCompoundDrawablesWithIntrinsicBounds() {
Drawable drawable = getResources().getDrawable(R.mipmap.edit_lock);
EditText editText_drawable = (EditText) findViewById(R.id.editText_drawable2);
editText_drawable.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
}
/**
* 測試EditText.setCompoundDrawables()
* <p>
* 可以在上、下、左、右設置圖標,如果不想在某個地方顯示,則設置爲null。
* <p>
* 但是Drawable必須要setBounds(Rect)。設置初始位置、寬和高等信息。
* <p>
* 即:使用前要先調用Drawable.setBounds(),可以調整圖片的大小和相對位置
*/
private void testSetCompoundDrawables() {
Drawable drawable = getResources().getDrawable(R.mipmap.edit_lock);
drawable.setBounds(0, 0, 40, 40);
EditText editText_drawable = (EditText) findViewById(R.id.editText_drawable);
editText_drawable.setCompoundDrawables(drawable, null, null, null);
}
/**
* 系統自帶的密碼開關輸入框的錯誤信息處理
*/
private void TextInputLyout_EditText() {
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) {
}
@Override
public void afterTextChanged(Editable s) {
if (mEditText.getText().length() > mTextInputLayout.getCounterMaxLength()) {
mTextInputLayout.setError("超出限定字數了...");
}
}
});
}
/**
* 自定義密碼開關輸入框的錯誤信息處理
*/
private void customizeEditText() {
mEditText_customize.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) {
}
@Override
public void afterTextChanged(Editable s) {
if (mEditText_customize.getText().length() > mTil_customize.getCounterMaxLength()) {
mEditText_customize.setError("超出限定字數了!!");
}
}
});
}
}
Demo效果圖
==注意==
- 添加庫的時候注意要加appcompat-v7庫,確保可以向後兼容
- TextInputLayout下的實際視圖層次結構不能保證以XML格式編寫視圖層次結構。 因此,對於TextInputLayout的子對象EditText(或子類TextInputEditText)想調用getParent()可能不會返回TextInputLayout. 如果您需要直接訪問視圖,建議設置一個android:id並使用findViewById(int).
- 一個TextInputLayout只能套一個EditText(或它的子類TextInputEditText)
- 當使用passwordToggleDrawable密碼開關圖片的時候,EditText end位置的 圖標時會被覆蓋的,爲了保證EditText end 位置Drawable的正常顯示,你需要在設置這些Drawables 的相對位置(start/end)爲絕對(left/right).(官方文檔說的,沒搞懂)
- 使用了TextInputLayout,和它的setError(),佈局所佔的位置會變多,設計佈局注意留適當的空間
- EditText的setError和passwordToggleDrawable的圖片會重疊,建議只用TextInputLatyout的setError或者重寫EditText的佈局,抉擇一個吧
- TextInputLayout.setError()注意調用setErrorEnabled(false)清空錯誤信息,不然會一直顯示
- 建議TextInputLayout只套一個EditText,放其他控件會出現焦點搶佔的問題(View的事件分發)
TextInputEditText
TextInputEditText是EditText的子類,說白了是爲了填EditText的坑的
當我們的界面處於全屏時,點擊一個EditText,默認情況下不是在它下面彈出鍵盤,而是進入到輸入法的一個全屏的輸入界面(通過配置android:imeOptions=”flagNoExtractUi”可以設爲直接在當前界面顯示)
如果我們給EditText 套上了一個TextInputLayout時,TextInputLayout會拿到EditText的hint顯示出來並把EditText本身的hint設爲空.這樣我們在全屏的輸入界面上,就顯示不出來我們設置hint,因此TextInputEditText重寫了EditText
小知識:EditText的imeOptions要與inputType同時使用,不然沒有反應
EditText與TextInputEditText效果區別圖
在EditText 設置android:drawableLeft Bug
今天在TextInputLayout設置了app:passwordToggleEnabled=”true”屬性的EditText設置androd:drawableLeft屬性時發現,只能顯示原圖,然後在代碼調用Drawable.setBounds()方式調整大小時,發現drawableLeft圖片直接不顯示了(估計源碼沒設計好)
而不調用 app:passwordToggleEnabled=”true”屬性,Drawable.setBounds()能正常使用
因此建議同學們,要麼使用原圖(美工切小圖),要麼不用passwordToggleEnabled屬性,自己自定義drawableLeft/drawableRight(建議)
TextInputLayout使用bug:
- 今天使用TextInputLyout.setError()發現以下bug,
Failed to inflate ColorStateList, leaving it to the framework
java.lang.RuntimeException: Failed to resolve attribute at index 0
android.content.res.TypedArray.getColor(TypedArray.java:401)
...
解決:
在佈局文件的TextInputLayout設置app:errorTextAppearance=”@style/Theme.AppCompat”,同學們使用過程中發現類似RuntimeException bug,同理設置樣式即可解決
總結
留個TODO,請求大神幫幫忙:
當使用passwordToggleDrawable密碼開關圖片的時候,EditText end位置的 圖標時會被覆蓋的,爲了保證EditText end 位置Drawable的正常顯示,你需要在設置這些Drawables 的相對位置(start/end)爲絕對(left/right).(官方文檔說的,沒搞懂)
官方用的矢量圖,自己的方案是找個寬高較小的圖片,或者重寫EditText,自定義View
本篇文章到此結束,歡迎關注,後續有補充的會即使更新,有問題也歡迎評論,共同成長