TextInputLayout是一个能够把EditText包裹在当中的一个布局,当输入文字时,它可以把Hint文字飘到EditText的上方,错误信息显示在editText的下方。
TextInputLayout用在登陆注册的界面上很常见,做出来的效果也很炫,下面我们就用TextInputLayout来创建一个登陆界面
首先先把需要的包通过依赖添加到我们的项目中
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:design:22.2.0'
compile 'com.android.support:appcompat-v7:22.2.0'
}
UI很简单,一个Login的标签和两个EditText (用户名,密码框),不居中再加上一个登陆按钮。
另一个需要注意的细节是设置好两个输入框的inputType ,第一个框设置为textEmail ,第二个框设置为textPassword,布局如下所示。
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
"match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:orientation="vertical">
"match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:text="Login"
android:textSize="30sp"
android:textColor="#333333"/>
"match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="0.5">
"@+id/text_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintTextAppearance="@style/hintStyle">
"@+id/user_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
android:hint="Username"/>
"match_parent"
android:layout_height="wrap_content"
app:hintTextAppearance="@style/hintStyle">
"@+id/pass_word"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="Password"/>
在setContentView()下面,初始化TextInputLayout 的引用。
TextInputLayout username = (TextInputLayout) findViewById(R.id.text_user_layout);
TextInputLayout password = (TextInputLayout) findViewById(R.id.text_pass_word_layout);
想要看到hint浮动的动画,还需要调用setHint
usernameWrapper.setHint("Username");
passwordWrapper.setHint("Password");
做完这个以后,这个应用已经完全符合material design了,运行程序,然后你会看到登录界面。
TextInputLayout另一个很赞的功能是,可以处理错误情况。通过验证用户输入,你可以防止用户输入错误的邮箱,或者输入不符合规则的密码。
有些输入验证,验证是在后台做得,产生错误后会反馈给前台,最后展示给用户。非常耗时而且用户体验差。最好的办法是在请求后台前做校验。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// STUB
}
});
其实,当这个方法被调用以后,就不需要键盘了。但是不幸的是,Android不会自动隐藏。怎么办呢?调用下面的方法吧。
private void hideKeyboard() {
View view = getCurrentFocus();
if (view != null) {
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).
hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
验证邮箱稍微有些复杂,我们可以用Apache Commons library 来做这个事。我这里用一个维基百科里的正则表达式。
/^[a-zA-Z0-9#_~!&'()*+,;=:."(),:;<>@\[\]\\]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*/
既然我们想验证一个string,我们必须依赖Pattern and Matcher,它们在java.util.regex下面。在Activity中导入它们。
private static final String EMAIL_PATTERN = "^[a-zA-Z0-9#_~!$&'()*+,;=:.\"(),:;<>@\\[\\]\\\\]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*$";
private Pattern pattern = Pattern.compile(EMAIL_PATTERN);
private Matcher matcher;
public boolean validateEmail(String email) {
matcher = pattern.matcher(email);
return matcher.matches();
}
密码验证相对简单,不同的组织有不同的验证方式。但是大都有最小长度限制。最合理的规则就是至少输入六位字符。
public boolean validatePassword(String password) {
return password.length() > 5;
}
之前已说过,TextInputLayout只是一个容器。不像LinearLayout and ScrollView,你可以直接获取它的子元素通过特定的方法(getEditText)。根本木有必要使用findViewById。
如果TextInputLayout 中没有EditText,getEditText 会返回null,你得注意下NullPointException了。
public void onClick(View v) {
hideKeyboard();
String username = usernameWrapper.getEditText().getText().toString();
String password = usernameWrapper.getEditText().getText().toString();
// TODO: Checks
// TODO: Login
}
TextInputLayout 错误处理简单而迅速。相关的方法有setErrorEnabled和setError。
setError会弹出红色的提示消息同时显示在EditText下面,如果传入的错误消息是null,之前的消息会被清除掉。这个方法还会使EditText 也变红色。
setErrorEnabled 是控制这个功能的。这会直接影响layout的大小。
还有一个需要注意的是,如果没有调用setErrorEnabled(true)但是调用了setError 方法并且传入了非空的消息,setErrorEnabled(true) 会被自动调用。
正确和错误情况我们已经说明了,下面就实现onClick 方法。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
hideKeyboard();
String username = layout_name.getEditText().getText().toString();
String password = layout_name.getEditText().getText().toString();
if (!validateEmail(username)) {
layout_name.setError("邮箱格式有误!");
} else if (!validatePassword(password)) {
layout_password.setError("密码格式错误!");
} else {
layout_name.setErrorEnabled(false);
layout_password.setErrorEnabled(false);
doLogin();
}
}
});
下面是空的登录方法:
public void doLogin() {
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_SHORT).show();
}
修改TextInputLayout背景
在TextInputLayout中配置
app:counterEnabled=”true”属性即可进行字数统计功能。
当然,你也可以指定最大输入的字符数,使用app:counterMaxLength=”15″属性
注意:在使用此属性时必须为TextInputLayout指定如下属性app:counterOverflowTextAppearance=”@style/MyOverflowText”
来改变文字超出时,提示文字的显示效果,否则程序将直接抛出异常,请注意,这是一个很大的坑,如果没有该属性的声明程序一定会报异常