Android Material Design系列之TextInputLayout

前言

TextInputLayout是一个可以把EditText包裹在当中的一个布局,当输入文字时,它能够把Hint文字飘到EditText的上方,错误信息显示在editText的下方。java

使用

TextInputLayout用在登录注册的界面上很常见,作出来的效果也很炫,下面咱们就用TextInputLayout来建立一个登录界面
首先先把须要的包经过依赖添加到咱们的项目中android

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界面

UI很简单,一个Login的标签和两个EditText (用户名,密码框),不居中再加上一个登录按钮。
另外一个须要注意的细节是设置好两个输入框的inputType ,第一个框设置为textEmail ,第二个框设置为textPassword,布局以下所示。web

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="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">
    <RelativeLayout android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="0.5"
                    android:orientation="vertical">

        <TextView android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_centerInParent="true"
                  android:gravity="center"
                  android:text="Login"
                  android:textSize="30sp"
                  android:textColor="#333333"/>

    </RelativeLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_weight="0.5">
        <android.support.design.widget.TextInputLayout
            android:id="@+id/text_input_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:hintTextAppearance="@style/hintStyle">

            <android.support.design.widget.TextInputEditText
                android:id="@+id/user_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="textEmailAddress"
                android:hint="Username"/>

        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:hintTextAppearance="@style/hintStyle">

            <android.support.design.widget.TextInputEditText
                android:id="@+id/pass_word"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="textPassword"
                android:hint="Password"/>

        </android.support.design.widget.TextInputLayout>
        <Button
            android:id="@+id/confirm"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="确认"/>

    </LinearLayout>



</LinearLayout>

去掉ActionBar

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
</style>

设置提示信息(hints)

在setContentView()下面,初始化TextInputLayout 的引用。正则表达式

TextInputLayout username = (TextInputLayout) findViewById(R.id.text_user_layout);
TextInputLayout password = (TextInputLayout) findViewById(R.id.text_pass_word_layout);

想要看到hint浮动的动画,还须要调用setHintapp

usernameWrapper.setHint("Username");
passwordWrapper.setHint("Password");

作完这个之后,这个应用已经彻底符合material design了,运行程序,而后你会看到登陆界面。
这里写图片描述ide

处理错误

TextInputLayout另外一个很赞的功能是,能够处理错误状况。经过验证用户输入,你能够防止用户输入错误的邮箱,或者输入不符合规则的密码。
有些输入验证,验证是在后台作得,产生错误后会反馈给前台,最后展现给用户。很是耗时并且用户体验差。最好的办法是在请求后台前作校验。svg

实现onClick 方法
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中导入它们。ui

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背景

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorAccent">#3498db</item>
</style>

这里写图片描述

字数统计功能

在TextInputLayout中配置
app:counterEnabled=”true”属性便可进行字数统计功能。
固然,你也能够指定最大输入的字符数,使用app:counterMaxLength=”15″属性

注意:在使用此属性时必须为TextInputLayout指定以下属性app:counterOverflowTextAppearance=”@style/MyOverflowText”

来改变文字超出时,提示文字的显示效果,不然程序将直接抛出异常,请注意,这是一个很大的坑,若是没有该属性的声明程序必定会报异常

这里写图片描述