Android TextInputLayout 示例

在本教程中,我们将深入研究 Android TextInputLayout 提供的功能。Android TextInputLayout 是一个设计组件,配备了 Material Design Support Library。

Android TextInputLayout

Android TextInputLayout 是 LinearLayout 的扩展。TextInputLayout 的主要用途是作为 EditText(或其子类)的包装器,并启用浮动提示动画。经验法则:TextInputLayout 应该包裹 TextInputEditText 而不是普通的 EditText为什么? TextInputEditText 是 EditText 的子类,设计用于作为 TextInputLayout 的子类。此外,使用 EditText 会收到警告:添加的 EditText 不是 TextInputEditText。请切换到使用该类。TextInputLayout 提供的远不止显示浮动提示标签。

Android TextInputLayout 功能

本教程将涵盖的一些功能包括:

  1. 启用/禁用浮动提示
  2. 启用/禁用浮动提示动画
  3. 显示错误消息
  4. 显示字符计数
  5. 警告用户当字符数超过其限制
  6. 自定义浮动提示、错误标签、字符计数的文本外观
  7. 密码可见性切换

我们将逐个查看这些功能,并在Android Studio项目中实现它们。

Android TextInputLayout示例项目结构

这是一个单Activity应用程序。我们将在布局、活动和styles.xml以及colors.xml文件中完成所有工作。首先,在build.gradle文件中添加设计支持库的依赖,如下所示。

compile 'com.android.support:design:25.3.1'

启用/禁用浮动提示

浮动提示在TextInputLayout中默认启用。要禁用它,我们需要在标签内添加以下属性:app:hintEnabled="false"。下面的xml代码来自activity_main.xml布局,包含三个EditText字段。

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">


        <android.support.design.widget.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            android:hint="TextInputEditText" />


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/activity_horizontal_margin">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Floating Hint Enabled Default" />

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


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:hintEnabled="false">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Floating Hint Disabled" />

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

</LinearLayout>
</ScrollView>

第三个EditText字段已禁用浮动提示。让我们看看上面的代码给我们的输出:

启用/禁用浮动提示动画

与前一个功能类似,默认情况下启用了浮动提示动画。要禁用它,我们需要在TextInputLayout标记内添加以下属性。app:hintAnimationEnabled="false"下面的xml代码来自activity_main.xml布局,并包含两种情况的EditText字段。

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/activity_horizontal_margin">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Floating Hint Enabled Default" />

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


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:hintAnimationEnabled="false">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Hint Animation Disabled" />

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

</LinearLayout>
</ScrollView>

上述代码的输出如下所示。值得注意的是,当焦点集中时,第二个EditText字段不会显示浮动提示动画。

样式化提示TextAppearance

使用自定义textColortextSize来设置提示的属性如下:app:hintTextAppearance="@style/HintText" HintText样式写在styles.xml中,如下所示

<style name="HintText" parent="TextAppearance.Design.Hint">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/colorPrimary</item>
    </style>

以下xml代码来自activity_main.xml布局,包含带有/不带有hintTextAppearance的EditText字段。

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/activity_horizontal_margin">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Floating Hint Enabled" />

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


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Custom Hint TextAppearance" />

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

</LinearLayout>
</ScrollView>

上述代码的输出如下。

字符计数器

字符计数器是许多应用程序使用的一个功能(记得Twitter的字符限制吗?)。将app:counterEnabled设置为true,并使用app:counterMaxLength设置TextInputLayout中要显示的最大字符数。字符计数器默认显示在EditText下方(右下角),在撰写本教程时,尚无更改位置的方法。定制计数器的样式类似于定制提示文本的样式,这次使用的是app:counterTextAppearance属性。我们在项目的styles.xml文件中添加了以下样式。

<style name="CounterText" parent="TextAppearance.Design.Counter">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/my_pink</item>
    </style>

以下xml代码来自activity_main.xml布局,其中包含默认字符计数器和自定义字符计数器的EditText字段。

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Character Counter Limit 10" />

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


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterTextAppearance="@style/CounterText"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Character Counter Custom TextAppearance" />

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

</LinearLayout>
</ScrollView>

以下是上述代码的输出。观察上述输出:

  • 第一个EditText字段在字符计数超过限制时会更改其计数文本颜色、提示文本颜色和指示器颜色。
  • 第二个EditText字段也会执行相同的操作,但是还会在限制超过时更改计数自定义文本颜色自定义文本大小

要指定字符计数器超过限制时需要的样式,我们需要使用接下来将看到的counterFlow属性。

字符计数器溢出

正如我们上面看到的,当字符计数超过定义的限制时,计数文本会使用counterFlow中定义的属性。如果这些属性不存在,则会使用默认的属性,就像我们在上面的输出中看到的那样。我们需要使用以下参数app:counterOverflowTextAppearanceCounterOverflow的样式位于styles.xml中:

 <style name="CounterOverFlow" parent="TextAppearance.Design.Counter.Overflow">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/my_orange</item>
    </style>

将以下代码片段添加到之前的activity_main.xml布局中:

<android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterOverflowTextAppearance="@style/CounterOverFlow"
            app:counterTextAppearance="@style/CounterText"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="CounterOverflow CustomTextAppearance" />

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

让我们再次运行应用程序。

错误标签

设置app:errorEnabledtrue允许我们在EditText字段下方的条件中显示错误文本。要为错误文本设置样式,我们将使用属性app:errorTextAppearance并将以下代码添加到我们的styles.xml文件中。

<style name="ErrorText" parent="TextAppearance.Design.Error">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/my_black</item>
    </style>

以下xml代码来自activity_main.xml布局,其中包含用于默认错误标签和自定义错误标签的EditText字段。

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:id="@+id/errorInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterOverflowTextAppearance="@style/CounterOverFlow"
            app:counterTextAppearance="@style/CounterText"
            app:errorEnabled="true"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:id="@+id/errorEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Default Error Label" />

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


        <android.support.design.widget.TextInputLayout
            android:id="@+id/customErrorInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterOverflowTextAppearance="@style/CounterOverFlow"
            app:counterTextAppearance="@style/CounterText"
            app:errorEnabled="true"
            app:errorTextAppearance="@style/ErrorText"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:id="@+id/customErrorEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Custom Error Label" />

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

</LinearLayout>
</ScrollView>

要显示错误文本,我们需要在MainActivity.java类中的TextInputLayout实例上调用setError(String)方法,如下所示。

package com.journaldev.featuresoftextinputlayout;

import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;

public class MainActivity extends AppCompatActivity {


    TextInputLayout errorInputLayout, customErrorInputLayout;
    TextInputEditText errorEditText, customErrorEditText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        errorEditText = (TextInputEditText) findViewById(R.id.errorEditText);
        errorInputLayout = (TextInputLayout) findViewById(R.id.errorInputLayout);

        customErrorEditText = (TextInputEditText) findViewById(R.id.customErrorEditText);
        customErrorInputLayout = (TextInputLayout) findViewById(R.id.customErrorInputLayout);

        errorEditText.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 (s.length() > errorInputLayout.getCounterMaxLength())
                    errorInputLayout.setError("Max character length is " + errorInputLayout.getCounterMaxLength());
                else
                    errorInputLayout.setError(null);

            }
        });

        customErrorEditText.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 (s.length() > customErrorInputLayout.getCounterMaxLength())
                    customErrorInputLayout.setError("Max character length is " + customErrorInputLayout.getCounterMaxLength());
                else
                    customErrorInputLayout.setError(null);

            }
        });


    }
}

在上面的代码中,我们在每个TextInputEditText实例上添加了一个TextChangedListener(它实现了TextWatcher)。当当前字符计数超过计数器最大限制时,我们显示错误标签。要清除错误标签,我们将setError()中的值设置为null。上面的代码给我们的输出是: 注意:文本字段的指示器使用与错误标签相同的颜色。它覆盖了由counterOverflow设置的颜色,因此具有最高优先级。

密码可见性切换

app:passwordToggleEnabled设置为true允许您显示/隐藏密码。要更改图标颜色,请使用app:passwordToggleTint。下面的xml代码来自activity_main.xml布局,并包含用于密码可见性切换的EditText字段(默认图标和带有色彩的图标)。

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterOverflowTextAppearance="@style/CounterOverFlow"
            app:counterTextAppearance="@style/CounterText"
            app:hintTextAppearance="@style/HintText"
            app:passwordToggleEnabled="true">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Password Visibility Toggle"
                android:inputType="textPassword" />

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


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterOverflowTextAppearance="@style/CounterOverFlow"
            app:counterTextAppearance="@style/CounterText"
            app:hintTextAppearance="@style/HintText"
            app:passwordToggleEnabled="true"
            app:passwordToggleTint="@color/my_orange">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Password Visibility Toggle Tint"
                android:inputType="textPassword" />

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

以下是上述代码显示的输出: 注意:我们可以使用app:passwordToggleDrawable自定义密码可见性切换的图标。这就结束了本教程。我们已经涵盖了TextInputLayout中的所有主要功能。您可以从以下链接下载Android TextInputLayout示例项目。它包含上面每个代码片段。

下载Android TextInputLayout项目

参考:Android官方文档

Source:
https://www.digitalocean.com/community/tutorials/android-textinputlayout-example