TextInputLayout可以说是用来升级EditText的,它是一个容器,内部也只能放一个子view也就是EditTxet,下面来看下效果
当EditText获得焦点的时候,hint提示会已动画效果跑到输入框的上方提示你这里需要输入什么内容,还可以记录输入字符的长度,对用户来说还是非常方便的!
- gradle需要引入degisn库的支持
compile 'com.android.support:design:23.2.0'
- 布局引入
<android.support.design.widget.TextInputLayout
android:id="@+id/usernameWrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
TextInputLayout 常用属性
- counterEnabled:是否启用计数器
- counterMaxLength:启用计数器时,最大字数限制(仅仅用做显示)
- counterOverflowTextAppearance:当字数超出计数器的最大限制时的字体格式
- hintAnimationEnabled:是否启用hint动画效果
- errorEnabled:是否显示错误信息
errorTextAppearance:错误信息的字体格式
1.为这两个输入框设置一些属性
final TextInputLayout name = (TextInputLayout) findViewById(R.id.usernameWrapper);
final TextInputLayout psd = (TextInputLayout) findViewById(R.id.passwordWrapper);
name.setHint("Username");
psd.setHint("Password");
psd.setCounterEnabled(true);//是否启用计数器
psd.setCounterMaxLength(15);//启用计数器时,最大字数限制(仅仅用做显示)
在这里还有个小坑,当你启用了计数器的时候输入的内容超出了给定值会直接被crash并抛出一大段异常,在这里给出解决办法,在values文件夹下的styles.xml中加入这行代码就ok了。
//这个textColorError 属性在这里定义是为了能在TextInputLayout的ErrorState下使用,你可以使用自己定义的color值,否则就会crash
<item name="textColorError">@color/design_textinput_error_color_light</item>
- TextInputLayout是一个容器所以我们要获得里面的EditText
EditText editText = psd.getEditText();
- 设置输入内容监听,同时使用TextInputLayout的Error提示
psd.getEditText().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) {
if (s.length() > 6) {
psd.setError("密码长度超出范围!当前长度为:" + s.length());
psd.setErrorEnabled(true);
} else {
psd.setErrorEnabled(false);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
在设置错误信息的时候需要注意的是,前后两次设置的内容不能是一样的否则就不会被处理,我们来看下源码就知道了
设置错误信息的方法这写了一句If we already have the same error, ignore如果是相同的错误信息将不会被理睬。
public void setError(@Nullable final CharSequence error) {
if (TextUtils.equals(mError, error)) {
// If we already have the same error, ignore
return;
}
mError = error;
if (!mErrorEnabled) {
if (TextUtils.isEmpty(error)) {
// If error isn't enabled, and the error is empty, just return
return;
}
// Else, we'll assume that they want to enable the error functionality
setErrorEnabled(true);
}
// Only animate if we've been laid out already
final boolean animate = ViewCompat.isLaidOut(this);
mErrorShown = !TextUtils.isEmpty(error);
if (mErrorShown) {
mErrorView.setText(error);
mErrorView.setVisibility(VISIBLE);
if (animate) {
if (ViewCompat.getAlpha(mErrorView) == 1f) {
// If it's currently 100% show, we'll animate it from 0
ViewCompat.setAlpha(mErrorView, 0f);
}
ViewCompat.animate(mErrorView)
.alpha(1f)
.setDuration(ANIMATION_DURATION)
.setInterpolator(AnimationUtils.LINEAR_OUT_SLOW_IN_INTERPOLATOR)
.setListener(new ViewPropertyAnimatorListenerAdapter() {
@Override
public void onAnimationStart(View view) {
view.setVisibility(VISIBLE);
}
}).start();
}
} else {
if (mErrorView.getVisibility() == VISIBLE) {
if (animate) {
ViewCompat.animate(mErrorView)
.alpha(0f)
.setDuration(ANIMATION_DURATION)
.setInterpolator(AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR)
.setListener(new ViewPropertyAnimatorListenerAdapter() {
@Override
public void onAnimationEnd(View view) {
mErrorView.setText(error);
view.setVisibility(INVISIBLE);
}
}).start();
} else {
mErrorView.setVisibility(INVISIBLE);
}
}
}
updateEditTextBackground();
updateLabelState(true);
}