Material Design 之 TextInputLayout和TextInputEditText

写在前面

更多Material Design 文章请看:
Material Design 之 Toolbar 开发实践总结
Material Design之 AppbarLayout 开发实践总结
Material Design 之 Behavior的使用和自定义Behavior
Material Design 之 TabLayout 使用
文本框相信大家都很熟悉,文本框可以让用户输入文本。它们可以是单行的,带或不带滚动条,也可以是多行的,并且带有一个图标。点击文本框后显示光标,并自动显示键盘。除了输入,文本框可以进行其他任务操作,如文本选择(剪切,复制,粘贴)以及数据的自动查找功能。这篇文章讲的就是Material Design 风格的文本框,它有有一些比较炫酷的动画效果(比如输入的时候,内嵌标签会浮动到内容的上方),此外还给我一些特别有用的功能,如错误提示、计数等等。Material Design 风格的文本框是用TextInputLayout 和TextInputEditText 两个View来实现的,该类support design 包中。下面就来看一下TextInputLayout 的具体用法。

TextInputLayout 使用

TextInputLayout介绍

首先来看一下TextInputLayout,TextInputLayout 是EditText(或者EditText子类)的一个包装类,它主要用于在用户输入文本的时候显示一个浮动标签,也支持显示错误信息和字符计数等功能。同样它也支持密码可见切换按钮,通过setPasswordVisibilityToggleEnabled(boolean)API 或者 xml 中的属性,如果设置该属性为可用(enable),那么当EditText 显示设置的密码时,会显示一个切换密码可见和隐藏的按钮。

注意:当使用密码切换按钮的时候,EditText 结束位置的 图标时会被覆盖的,为了保证EditText 结束位置Drawable的正常显示,你需要设置这些Drawables 的相对位置( 相对start的位置/相对结束的位置)。

图标覆盖,如下图:

override_drawable.png

如上图所示,切换密码可见的按钮(眼睛图标)和错误提示的图标 覆盖在一起了。

TextInputLayout 重要方法和属性

来看一下TextInputLayout 的一些重要方法和属性:

  • app:counterEnabled 字符计数是否可用
    代码中对应的方法为:setCounterEnabled(boolean)

  • app:counterMaxLength 计数最大的长度
    代码中对应的方法为:setCounterMaxLength(int )

  • app:counterOverflowTextAppearance 计数超过最大长度时显示的文本样式

  • app:counterTextAppearance 显示的计数的文本样式。

  • app:errorEnabled 显示错误信息是否可用

  • app:errorTextAppearance 显示错误信息的文本样式

  • android:hint 浮动标签
    代码对应方法:setHint(CharSequence)

  • app:hintAnimationEnabled 控制是否需要浮动标签的动画
    代码对应方法:setHintAnimationEnabled(boolean)

  • app:hintEnabled 控制是否显示浮动标签
    代码对应方法:setHintEnabled(boolean)

  • app:hintTextAppearance 浮动标签的文本样式
    代码对应方法:setHintTextAppearance(int)

  • app:passwordToggleDrawable 密码可见切换图标
    代码对应方法:setPasswordVisibilityToggleDrawable(int)或者setPasswordVisibilityToggleDrawable(Drawable)

  • app:passwordToggleEnabled 控制是否显示密码可见切换图标
    代码对应方法:setPasswordVisibilityToggleEnabled(boolean)

TextInputLayout 使用示例

了解了以上的属性和方法后,我们看一下具体使用:
1,带浮动标签的文本框
代码如下:

     />
    <android.support.design.widget.TextInputLayout
        android:id="@+id/text_input_layout_user"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        app:counterOverflowTextAppearance="@style/TextOverCount"
        android:scrollbarAlwaysDrawHorizontalTrack="true"
        android:textColorHint="@color/colorHint"
        >
         <EditText
             android:id="@+id/text_input_user"
             android:layout_width="match_parent"
             android:layout_height="48dp"
             android:hint="用户名"
             android:inputType="text"
             android:textColor="@color/black"
             />

    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/text_input_layout_phone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        app:counterOverflowTextAppearance="@style/TextOverCount"
        android:scrollbarAlwaysDrawHorizontalTrack="true"
        android:textColorHint="@color/colorHint"
        >
        <EditText
            android:id="@+id/text_input_phone"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:hint="手机号码"
            android:inputType="number"
            android:textColor="@color/black"
            />

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

效果如下:

Floating_label.gif

2,带字符计数的文本框
布局:

<android.support.design.widget.TextInputLayout
        android:id="@+id/text_input_layout_user"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:textColorHint="@color/colorHint"
        >
         <EditText
             android:id="@+id/text_input_user"
             android:layout_width="match_parent"
             android:layout_height="48dp"
             android:hint="用户名"
             android:inputType="text"
             android:textColor="@color/black"
             />

    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/text_input_layout_phone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"

        android:scrollbarAlwaysDrawHorizontalTrack="true"
        android:textColorHint="@color/colorHint"
        >
        <EditText
            android:id="@+id/text_input_phone"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:hint="手机号码"
            android:inputType="number"
            android:textColor="@color/black"
            />
    </android.support.design.widget.TextInputLayout>

在Activity 中设置,计数的长度:


        mTextInputLayoutUser = (TextInputLayout) findViewById(R.id.text_input_layout_user);
        //设置可以计数
        mTextInputLayoutUser.setCounterEnabled(true);
        //计数的最大值
        mTextInputLayoutUser.setCounterMaxLength(20);

效果如下:

count_edittext.gif

如上图所示,右下角会自动计数,当超过最大值时,计数文本、浮动标签和下标线都变成了红色,然后我们也可以用上面介绍的属性来更改:
添加代码

app:counterOverflowTextAppearance="@style/TextOverCount"

style 的代码如下:


    <style name="TextOverCount" parent="Base.TextAppearance.AppCompat.Light.Widget.PopupMenu.Small">
      <item name="android:textColor">@android:color/holo_green_light</item>
    </style>

效果如下:

count_over_apprence.png

如上图,将显示的颜色改为了绿色,当然也可以在style中改字体的大小,在添加一个item 就行

<item name="android:textSize">20sp</item>  

** 更改计数文本的显示样式是一样的,定义一个style ,然后通过app:counterTextAppearance 设置就行。**

** 3,显示密码可见和隐藏的切换按钮**
代码如下:

 <android.support.design.widget.TextInputLayout
        android:id="@+id/text_input_layout_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:textColorHint="@color/colorHint"
        app:passwordToggleEnabled="true"
        app:passwordToggleTint="@color/colorHint"
        app:passwordToggleDrawable="@drawable/ic_eye_grey_24dp"
        >

        <android.support.design.widget.TextInputEditText
            android:id="@+id/text_input_password"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:hint="密码"
            android:textColor="@color/black"
            android:inputType="textPassword"
            android:singleLine="true"
            />
    </android.support.design.widget.TextInputLayout>

效果如下:

toggle.gif

如上图,可以看到,右边多了一个图标,点击图标可以使密码是明文或者隐藏。只是在布局文件中添加了几个属性

        app:passwordToggleEnabled="true"
        app:passwordToggleTint="@color/colorHint"
        app:passwordToggleDrawable="@drawable/ic_eye_grey_24dp"

当然了,也可依在代码中设置,一样的效果,不在演示。
4, 显示错误信息
TextInputLayout 是可以显示错误信息的,这种需求很常见没,比如登录的时候密码错误,给出相应的提示,比Toast 提示更加友好。
代码如下:

        mTextInputLayoutPassword = (TextInputLayout) findViewById(R.id.text_input_layout_password);
        mInputEditTextPassword = (TextInputEditText) findViewById(R.id.text_input_password);

        mInputEditTextPassword.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) {
                mTextInputLayoutPassword.setErrorEnabled(false);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String password = mInputEditTextPassword.getText().toString();
                if(TextUtils.isEmpty(password)||password.length()<6){
                    mTextInputLayoutPassword.setError("密码错误不能少于6个字符");
                }

            }
        });

效果如下:

error_tip.gif

当密码不正确的时候,显示错误提示,当内容发生变幻的时候,记得调用

mTextInputLayoutPassword.setErrorEnabled(false);

否则错误信息会一直显示界面上。

** 当然有些时候我们不需要浮动标签,或者不需要浮动标签的动画,我们可以控制,将对应属性设置为false就行了。**

TextInputEditText 使用

上面讲了TextInputLayout的使用,那么TextInputEditText是干什么的呢? 其实就是一个EditText 的子类,上面讲的所有功能,TextInputLayout 里面包的子View既可以是EditText,也可以是TextInputEditText,效果是一样的。根据文档的解释,官网原文:A special sub-class of EditText
designed for use as a child of TextInputLayout。Using this class allows us to display a hint in the IME when in 'extract' mode.

解释:TextInputEditText 是 EditText 的子类,专门用作TextInputLayout的子View。它允许再`extract`模式(提取模式)下显示浮动标签。

也看过一些文章说,横屏模式EditText 不显示浮动标签,TextInputEditText 会显示浮动标签,但是我测试了一下,并没有发现所说的EditText 不显示浮动标签,TextInputEditText 会显示浮动标签。如果有知道的,请在评论区告知一下。,测试效果如下:(上看两个是EditText,最后一个是TextInputEditText)

text_input_edit.gif

** TextInputEditText 、EditText 作为TextInputLayout 的子View使用差别很小,既然Google 说在extract 模式下TextInputEditText 更好,那我们开发中使用TextInputEditText配合TextInputLayout使用就好了。**

另外,上面讲了TextInputLayout 可以显示错误信息,TextInputEditText也是可以显示错误信息的,用下面两个方法:

mInputEditTextUser.setError("格式不正确");
//或者
mInputEditTextUser.setError("格式不正确",getDrawable(R.drawable.activity_close)); 
error_tip2.png

最后

以上就是TextInputLayout和TextInputEditText 的全部内容,Demo 请戳MaterialDesignSamples。元旦之前来一发,祝大家元旦快乐!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,924评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,902评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,716评论 0 239
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,783评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,166评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,510评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,784评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,476评论 0 196
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,196评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,459评论 2 243
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,978评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,321评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,964评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,046评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,803评论 0 193
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,530评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,420评论 2 265

推荐阅读更多精彩内容