前言
源碼傳送門 https://github.com/xiehui999/fuseProgram
在 Material Design出現之前,如果我們想寫一個登陸界面是不是一般都寫兩組TextView,EditText及一個Button,如果你想在賬號和密碼后面加一個計數的功能,又需要加控件并且要自己實現計數,或者在密碼框后面加個類似眼睛的密碼顯示開關,或者你想加一個賬號或者密碼輸入無效或者錯誤的提醒,一般是顯示一個Toast或者使用EditText的setError設置,不過體驗并不是太好,等等這些麻煩的的處理在Material Design TextInputLayout出現后得到了極大改善,我們可以做最少的事達到最好的效果,今天的這篇文章就是通過一個登陸界面來學習TextInputLayout的API重要方法及其使用。先來一張效果圖
添加依賴
dependencies {
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:design:24.2.0'
}
使用
在TextInputLayout官方文檔API中描述它是一種新的繼承自LinearLayout的布局,使用時只能包含一個EditText或其子類的控件,該布局可以通過設置hint和Error顯示浮動標簽。接下我們看看布局文件
<LinearLayout
android:id="@+id/account_login_form"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:id="@+id/accountinput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_account"
>
<EditText
android:id="@+id/account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:inputType="phone"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/passwordinput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_password"
>
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/account_sign_in_button"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/login_btn"
android:textColor="@color/btninvalid"
android:text="@string/action_sign_in"
android:textStyle="bold"/>
</LinearLayout>
使用其實很簡單,只需要一個TextInputLayout(需要全路徑)容器并在其中加一個EditText(或子類),需要注意的是一個TextInputLayout有且只能對應一個EditText。在TextInputLayout加入android:hint="賬號"就可以顯示一個浮動標簽了,效果圖如上,還可以通過下面代碼將浮動標簽關閉,如果關閉的話,設置hint也就沒有效果了,默認是開啟的。
app:hintEnabled="false"
對于android:hint="賬號"屬性在TextInputLayout或者在EditText中設置都可以達到我們浮動標簽的效果,但是不能在兩者中同時使用設置hint,當兩者同時使用時沒有獲取焦點時都會顯示hint(兩個hint重疊顯示),獲取焦點時TextInputLayout設置的hint會成為懸浮標簽,但是此時EditText設置的hint不會消失,有輸入內容時才會消失,具體原因可以自己閱讀源碼查看,代碼不多,很容易看出來。對于浮動標簽顯示隱藏切換有一個過渡動畫,可以通過 app:hintAnimationEnabled="boolean"設置。
如果我們此時想在賬號那一欄后面加個字數統計,例如一般情況我們的賬號是固定位數的,如果使用手機號作為我們的登錄賬號,此時我們加一個統計輸入長度可以提示用戶當然也可以超過位數時限制其輸入,我們只需要在TextInputLayout加入
app:counterEnabled="true"
默認是關閉的,當然我們可以設置一個輸入的最大長度,此處設置11.
app:counterMaxLength="11"
當我們設置輸入的最大技術長度11時并不是到達11后不能再輸入計數,而是會以一種顏色提示用戶強調超過設置長度。
TextInputLayout提供了設置錯誤提醒的功能,在此篇文章中我們用手機號及密碼至少6位做判斷,
if (TextUtils.isEmpty(account)||!isAccountValid(account)) {
accountinput.setError(getString(R.string.error_invalid_account));
}
if (TextUtils.isEmpty(password)||!isPasswordValid(password)) {
passwordinput.setError(getString(R.string.error_invalid_password));
}
private boolean isAccountValid(String name) {
//TODO: Replace this with your own logic
Pattern pattern= Pattern.compile("^(13[0-9]|14[5|7]|15\\d|17[6|7]|18[\\d])\\d{8}$");
return pattern.matcher(name).matches();
}
private boolean isPasswordValid(String password) {
//TODO: Replace this with your own logic
return password.length() > 6;
}
當我們輸入不符合規則,設置錯誤,顯示效果如下,
對于設置錯誤,可以通過app:errorEnabled="boolean"或者代碼accountinput.setEnabled(boolean);將其打開或者關閉,當通過accountinput.setError()設置錯誤時源碼中默認調用setEnabled(true)打開,無需自己再次調用,還有一個注意的地方設置后不會自動取消,需要自己調用accountinput.setError(null);取消錯誤提示。例如在上面圖示提示錯誤后,我們在編輯該EditText時需要取消錯誤提示,那么我們可以通過addTextChangedListener監聽,代碼如下
mAccountView.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(accountinput.getError()!=null){
accountinput.setError(null);
}
}
});
當我們編輯時回調執行,我們通過getError獲取設置的錯誤信息,如果設置的有內容則返回設置的字符,默認為null。
對于輸入密碼的空間我們通過TextInputLayout中EditText 的android:inputType="textPassword"設置輸入密碼,此時我們可以在右側看到一個眼睛的密碼開關實現將密碼顯示或隱藏。如果我們不想顯示這個眼睛圖標可以在TextInputLayout中加入
app:passwordToggleEnabled="false"
此時就看不到眼睛的圖標,密碼也不在隱藏,當我們想將眼睛的圖標設置為我們自己設計的圖標時,可以通過下面代碼設置
app:passwordToggleDrawable="@drawable/common_full_open_on_phone"
我們還可以通過passwordToggleTint給圖標設置著色并且通過passwordToggleTintMode設置對應模式,達到更好看的效果。
是不是很簡單,這些功能要在之前布局肯定需要一大堆代碼的,而現在很簡單,只要幾行代碼
自定義EditText下劃線樣式
默認情況下EditText的下劃線是灰色的,當獲取焦點時顏色是colorAccent,如上圖,如果我們想自定義,可以給TextInputLayout加一個theme,如下代碼
android:theme="@style/customLineColor"
customLineColor樣式為colorControlNormal為沒有獲取焦點時的顏色,colorControlActivated為獲取焦點時的顏色,這樣就可以設置我們想要的顏色了。
<style name="customLineColor" parent="Theme.AppCompat.Light">
<item name="colorControlNormal">@color/colorAccent</item>
<item name="colorControlActivated">@color/drawerTextColor</item>
</style>
自定義浮動標簽
默認情況下浮動標簽的顏色也是colorAccent,我們可以通過hintTextAppearance設置浮動標簽字體樣式,如
app:hintTextAppearance="@style/hintAppearance",
<style name="hintAppearance" parent="TextAppearance.AppCompat">
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/colorPrimary</item>
</style>
自定義錯誤提示信息
app:errorTextAppearance="@style/errorAppearance"
<style name="errorAppearance" parent="TextAppearance.AppCompat">
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/red</item>
</style>
自定義超出計數最大長度樣式
app:counterOverflowTextAppearance="@style/counterOverflowTextAppearance"
<style name="counterOverflowTextAppearance" parent="TextAppearance.AppCompat">
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/red</item>
</style>
監控虛擬鍵盤
通過上面的介紹,我們將TextInputLayout的使用及常用的設置都已經都介紹了,既然文章名字是登錄界面,下面簡單介紹一下其他一些比較多登錄界面的一些實現。如當焦點在賬戶上,我們輸入完成后直接點擊虛擬鍵盤上的下一項時焦點直接跳到密碼項,密碼輸入完成,直接可以點擊虛擬鍵盤的確定就可以登錄,該怎么實現呢。如下
在賬號的EditText中加入
android:imeActionId="@+id/password"
android:imeOptions="actionNext"
在密碼的EditText中加入
android:imeActionId="@+id/account_sign_in_button"
android:imeOptions="actionDone"
mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
if ( id == EditorInfo.IME_ACTION_DONE) {
InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
//inputMethodManager.showSoftInput(getWindow().getDecorView(),InputMethodManager.SHOW_FORCED);//顯示
inputMethodManager.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(),InputMethodManager.RESULT_UNCHANGED_SHOWN);
//attemptLogin();
startLogin();
return true;
}
return false;
}
});
動態監測登錄按鈕
在支付寶中,當賬戶名或者密碼有沒填的項,登錄按鈕就是不可點擊的,并通過樣式給用戶反饋是不是可以點擊。這個也很簡單,只需要給兩個EditText設置addTextChangedListener監聽,監聽兩個控件只有有沒填項就將登錄按鈕設置為不可以點擊,否則可以點擊,核心代碼
if (account.equals("")||password.equals("")){
mAccountSignInButton.setClickable(false);
mAccountSignInButton.setTextColor(getResources().getColor(R.color.btninvalid));
}else{
mAccountSignInButton.setClickable(true);
mAccountSignInButton.setTextColor(getResources().getColor(R.color.white));
}
多賬號自動提示
AutoCompleteTextView是EditText的子類,可以實現自動提示功能該控件有一個setAdapter方法,可以監測我們輸入的內容在傳入的適配器中有數據時會自動彈出下拉提示,在文章開始效果圖已經展示,代碼簡單實現
private String[] accounts = { "18236593333", "13463373657", "18235784765", "18234637686" };
ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,accounts);
mAccountView.setAdapter(arrayAdapter);//輸入至少兩個字符才會提示