TextInputLayout

转载:http://www.jcodecraeer.com/a/basictutorial/2015/0821/3338.html


本教程中,我将再次讨论Material Design。Google I/O 2015 对于每一个开发者来说都是一个重大的事件,设计当然也是谈资之一。

谷歌意识到向后兼容是实现material design的重要部分。当然support library,比如appcompat-v4 和 appcompat-v7是解决方案的一部分。

但是Theme.AppCompat 并没有实现谷歌官方应用中用到的每个material组建。其中一个重要的特性就是AppCompat theme没有提供一个显示在EditText上方的浮动标签。你可以从下方的途中知晓我说的是什么。 

blob.png

在Google I/O 2015期间,安卓团队发布了一个崭新的兼容库,Design Support Library。它简直就是为解决这个问题而生的。本教程将演示如何使用Design Support Library中的TextInputLayout控件。

1. 实现 TextInputLayout

第一步: 创建一个新的项目

在Android Studio中 选择New > New project 。填入所需的信息然后创建项目。我的例子的target api是17,这是Design Support Library支持的最小api版本。这个级别的api基本上已经支持绝大多数设备了。我把主activity命名为LoginActivity,它的布局文件命名为activity_login.xml。

创建完项目之后,在主activity中把Android Studio自动产生的onCreateOptionsMenu 和onOptionsItemSelected方法删掉。我们要创建的登陆界面不需要菜单所以删掉这些方法是ok的。记得也删掉res/menu目录中的XML 菜单文件。

第二步 :导入Support Library

要使用TextInputLayout控件,你需要导入两个Library。第一个是appcompat-v7,它确保material style可以向后兼容。第二个是Design Support Library。在你的build.gradle文件中,添加如下依赖:

1
2
3
4
5
6
dependencies {
     compile fileTree(dir:  'libs' , include: [ '*.jar' ])
  
     compile  'com.android.support:design:22.2.0'
     compile  'com.android.support:appcompat-v7:22.2.0'
}

如果Gradle没有自动询问同步项目,选择build菜单中的Make module 'app' ,或者按F9。这样Android Studio 编译系统会自动获取必要的资源,然后你就能够使用需要的类了。

第三步 :设计用户界面

这个项目的用户界面非常简单。它显示了一个“欢迎”文字(可以很容易替换成logo什么的)与两个EditText元素,一个是为用户名准备的,一个是为密码准备的。布局中还包含了一个触发登陆流程的按钮。背景颜色是扁平风格的灰色。

另一个重要的细节是记得正确设置EditText的inputType属性。第一个EditText的inputType应该设置成textEmail,而第二个应该设置成textPassword。下面是布局的样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<LinearLayoutxmlns:android= "http://schemas.android.com/apk/res/android"
     xmlns:tools= "http://schemas.android.com/tools"
     android:background= "#e3e3e3"
     android:layout_width= "match_parent"
     android:layout_height= "match_parent"
     android:padding= "@dimen/activity_horizontal_margin"
     tools:context= ".LoginActivity"
     android:orientation= "vertical" >
  
     <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= "Welcome"
             android:textSize= "30sp"
             android:textColor= "#333333" />
  
     </RelativeLayout>
  
  
     <LinearLayout
         android:layout_width= "match_parent"
         android:layout_height= "wrap_content"
         android:layout_weight= "0.5"
         android:orientation= "vertical" >
  
         <EditText
             android:id= "@+id/username"
             android:layout_width= "match_parent"
             android:layout_height= "wrap_content"
             android:inputType= "textEmailAddress" />
  
         <EditText
                 android:id= "@+id/password"
                 android:layout_width= "match_parent"
                 android:layout_height= "wrap_content"
                 android:inputType= "textPassword" />
  
         <Button
             android:id= "@+id/btn"
             android:layout_marginTop= "4dp"
             android:layout_width= "match_parent"
             android:layout_height= "wrap_content"
             android:text= "Login" />
  
     </LinearLayout>
  
</LinearLayout>

你可能还想去掉app bar,也就是过去说的actionbar,编辑style.xml文件:

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

第四步: 使用TextInputLayout

我们总算到了本教程最有趣的部分。TextInputLayout控件和LinearLayout完全一样,它只是一个容器。跟ScrollView一样,TextInputLayout只接受一个子元素。子元素需要是一个EditText元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
<android.support.design.widget.TextInputLayout
     android:id= "@+id/usernameWrapper"
     android:layout_width= "match_parent"
     android:layout_height= "wrap_content" >
  
     <EditText
         android:id= "@+id/username"
         android:layout_width= "match_parent"
         android:layout_height= "wrap_content"
         android:inputType= "textEmailAddress"
         android:hint= "Username" />
  
</android.support.design.widget.TextInputLayout>

注意这里我在EditText中指定了另一个参数,hint。就如你知道的,这个属性允许你在EditText的内容为空的时候显示一个自定义的提示。一旦用户开始输入,hint会消失。这并不理想,因为用户丢失了他们输入信息的上下文提示。

有了TextInputLayout,这将不再是问题。一个单一的EditText 在输入文字的时候会隐藏hint,而被包含在TextInputLayout中的EditText则会让hint变成一个在EditText上方的浮动标签。同时还包括一个漂亮的material动画。

接下来,我们对password输入框做同样的事情。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<android.support.design.widget.TextInputLayout
     android:id= "@+id/passwordWrapper"
     android:layout_width= "match_parent"
     android:layout_height= "wrap_content"
     android:layout_below= "@id/usernameWrapper"
     android:layout_marginTop= "4dp" >
  
     <EditText
         android:id= "@+id/password"
         android:layout_width= "match_parent"
         android:layout_height= "wrap_content"
         android:inputType= "textPassword"
         android:hint= "Password" />
  
</android.support.design.widget.TextInputLayout>

现在如果你运行应用,什么也不会发生。当然,EditText的hint会表现的跟预期一致。但是没有material动画也没有浮动标签。为什么会这样?我们还缺少一些代码。

第五步: 设置 Hints

下面是setContentView方法,初始化对theTextInputLayout视图的引用。

1
2
final TextInputLayout usernameWrapper = (TextInputLayout) findViewById(R.id.usernameWrapper);
final TextInputLayout passwordWrapper = (TextInputLayout) findViewById(R.id.passwordWrapper);

要让浮动标签动起来,你只需设置一个hint,使用setHint方法:

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

然后你就完成了。你的登陆界面现在很好的遵循了material设计规范。运行项目查看你的登陆界面。

blob.png


2. 处理错误

TextInputLayout的另一个特色是它可以处理错误。通过验证输入,你可以防止用户输入无效的邮箱地址或者是太短的密码。如果没有验证,后台可能反馈回不正确的结果呈现给用户。对于用户来说既浪费了时间又体验不好。在发送到后台之前你应该先检查输入的正确性。

第一步: 实现 onClick 方法

首先你需要处理按钮的点击。有许多方法处理按钮的点击。其中一种就是写一个自定义的方法然后在xml中通过onClick属性指定,我喜欢setOnClickListener的方式,但这只是个人喜好。

1
2
3
4
5
6
btn.setOnClickListener( new  View.OnClickListener() {
     @Override
     public void onClick(View v) {
         // STUB
     }
});

我们知道当这个方法调用之后,用户不再需要键盘。不幸的是,如果你不告诉它,安卓不会自动的隐藏虚拟键盘。在onClick方法体中调用hideKeyboard。

1
2
3
4
5
6
7
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。

我使用了Wikipedia 上关于邮箱验证的指导,写了如下的正则表达式。

1
/^[a-zA-Z0-9 #_~!$&'()*+,;=:."(),:;<>@\[\]\\]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$/

注:这个正则表达式的意思我就不翻译了,如果你不熟悉正则表达式看了也没啥用。


因为我们想验证字符串,我必须依赖Pattern和Matcher两个类。includeava.util.regex 包。实现如下的方法:

1
2
3
4
5
6
7
8
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();
}

密码的验证简单的多。很多组织为密码的验证采用了不同的策略,但是所有人都会限制最短长度。合理的密码应该不低于6个字符。

1
2
3
public boolean validatePassword(String password) {
     return  password.length() > 5;
}

第三步: 获取数据

就如我说的,TextInputLayout只是一个容器,但是和LinearLayout和ScrollView不同,你可以使用一个特殊的方法获得子元素,getEditText,不需要使用findViewById

1
2
3
4
5
6
7
8
9
10
public void onClick(View v) {
     hideKeyboard();
      
     String username = usernameWrapper.getEditText().getText().toString();
     String password = passwordWrapper.getEditText().getText().toString();
      
     // TODO: Checks
      
     // TODO: Login
}

第四步: 显示错误

TextInputLayout的错误处理简单快速。需要的方法是setErrorEnabled和setError。

setError设置一个红色的错误消息,显示在EditText的下面。如果传入的参数为null,错误消息将清空。并且它会改变整个EditText控件为红色。

setErrorEnabled开启错误提醒功能。这直接影响到布局的大小,增加底部padding为错误标签让出空间。在setError设置错误消息之前开启这个功能意味着在显示错误的时候布局不会变化。你可以把这两个方法结合起来验证下我所说的。

另一个有趣的事实是如果错误功能未开启但是你调用了传入非null参数的setError,那么setErrorEnabled(true)将自动被调用。

现在我们定义了什么是错误的什么是正确的,也知道了如何获取EditText中的数据以及显示可能的错误,onClick方法的实现就很简单了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void onClick(View v) {
     hideKeyboard();
  
     String username = usernameWrapper.getEditText().getText().toString();
     String password = usernameWrapper.getEditText().getText().toString();
     if  (!validateEmail(username)) {
         usernameWrapper.setError( "Not a valid email address!" );
     else  if  (!validatePassword(password)) {
         passwordWrapper.setError( "Not a valid password!" );
     else  {
         usernameWrapper.setErrorEnabled( false );
         passwordWrapper.setErrorEnabled( false );
         doLogin();
     }
}

我添加了一个doLogin方法,但是目前它是空的因为这超出了本教程的范围。

1
2
3
4
public void doLogin() {
     Toast.makeText(getApplicationContext(),  "OK! I'm performing login." , Toast.LENGTH_SHORT).show();
     // TODO: login procedure; not within the scope of this tutorial.
}

3. 样式

你可能还想做最后一件事,改变TextInputLayout控件的颜色。默认AppCompact会把它设置成绿色的,但是很有可能这个颜色会和你的颜色主题(color palette)冲突。

谷歌把Design Support Library写的很好。每一个控件的颜色都是直接通过主题颜色绘制的,在 style.xml 中指定。打开它添加colorAccent 到主题以改变表单的颜色。

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

blob.png

总结

本教程中,我们看到了如何实现新的布局元素TextInputLayout,多亏有了刚刚引入的Design Support Library。

设计范例中,控件的实现需要让用户在输入的过程中不会丢失上下文信息,它是在去年跟Material Design一起被谷歌介绍的。在这之前,没有让开发者将这个控件应用到实际项目中的支持库。现在,如果你的应用有类似数据输入的地方,你终于可以完全遵循material design 了。

<think>首先,用户的问题是关于Google TextInputLayout的使用方法或实现功能。根据系统指令,我需要使用中文回答,结构清晰,帮助用户逐步解决问题。同时,我必须遵守所有格式要求:行内数学表达式用$...$,独立公式用$$...$$,LaTeX语法正确。 用户提到了参考站内引用,但这些引用是关于Android Material TextInputLayout的,特别是密码显示/隐藏功能。引用[1]和[2]描述了如何使用TextInputLayout来实现密码输入框的明文显示和隐藏功能,以及浮动标签功能。 用户意图似乎是查找如何实现TextInputLayout的特定功能,比如密码切换或浮动标签。所以,我应该基于这些引用构建回答。 回答结构: - 先介绍TextInputLayout是什么。 - 然后详细说明如何使用它,包括密码切换功能和浮动标签功能。 - 提供代码示例,因为用户问题涉及实现功能。 - 确保回答真实可靠,基于Android文档或常见实践。 关键点从引用: - 引用[1]:使用`app:passwordToggleEnabled="true"`来启用密码显示/隐藏按钮,需要com.android.support:design版本24以上。 - 引用[2]:TextInputLayout作为EditText的容器,提供浮动标签功能。 我还需要生成相关问题,在最后添加。 步骤: 1. **介绍TextInputLayout**:解释它是Android Material Design组件的一部分,用于增强EditText的功能。 2. **实现浮动标签功能**:描述如何设置TextInputLayout来显示浮动标签。 3. **实现密码切换功能**:详细说明如何启用密码显示/隐藏按钮。 4. **提供代码示例**:给出一个简单的XML布局代码示例,展示TextInputLayout的使用。 5. **注意事项**:提到依赖版本要求。 6. **生成相关问题**:在回答末尾添加相关问题。 确保LaTeX:用户问题中没有数学表达式,所以可能不需要使用$...$或$$...$$,除非我引入数学概念。但指令说所有行内数学表达式必须使用$...$,所以如果涉及,要用。但在Android开发中,不太可能有数学,所以可能不需要。 引用标识:在回答中引用的段落末尾添加引用标识。引用来自用户提供的参考,所以我可以使用[^1]和[^2]来引用它们。 最终回答结构: - 开头:简要介绍TextInputLayout。 - 部分1:实现浮动标签功能。 - 部分2:实现密码切换功能。 - 代码示例。 - 注意事项。 - 相关问题。 相关问题生成: - 基于用户问题,生成关于TextInputLayout的更多细节或相关主题的问题。 例如: 1. 如何在TextInputLayout中添加错误提示? 2. TextInputLayout的其他高级功能有哪些? 3. 如何自定义TextInputLayout的样式? 现在,构建回答内容。</think>### Google TextInputLayout 使用方法与实现功能 TextInputLayoutAndroid Material Design 组件库的一部分,它作为 EditText 的容器,提供增强功能如浮动标签(floating label)和密码显示/隐藏切换按钮。这有助于提升用户体验和界面美观度。下面我将逐步介绍如何实现这些功能,确保回答基于 Android 官方文档和常见实践。所有代码示例使用 Kotlin 和 XML 布局格式。 #### 1. **实现浮动标签功能** TextInputLayout 的核心功能之一是浮动标签。当用户点击 EditText 时,提示文本(hint)会自动浮动到左上角,提供清晰的输入引导。这不需要额外代码,只需在 XML 布局中正确配置。 - **步骤**: 1. 在项目的 `build.gradle` 文件中添加 Material Design 依赖(确保版本兼容)。 2. 在 XML 布局文件中,使用 `TextInputLayout` 包裹 `EditText`。 3. 设置 `EditText` 的 `hint` 属性,TextInputLayout 会自动处理浮动动画。 - **示例代码**: ```xml <com.google.android.material.textfield.TextInputLayout android:id="@+id/textInputLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="用户名" <!-- 浮动标签文本 --> app:layout_constraintTop_toTopOf="parent"> <EditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="text" /> <!-- 普通文本输入 --> </com.google.android.material.textfield.TextInputLayout> ``` - **效果**:用户点击 EditText 时,提示文本“用户名”会平滑移动到左上角,避免遮挡输入内容[^2]。 #### 2. **实现密码显示/隐藏切换功能** 对于密码输入框,TextInputLayout 支持添加一个眼睛图标按钮,允许用户切换密码的明文显示。这需要启用 `passwordToggleEnabled` 属性,并确保使用兼容的 Material Design 版本(24.0.0 或更高)。 - **步骤**: 1. 在 `TextInputLayout` 中设置 `app:passwordToggleEnabled="true"`。 2. 在 `EditText` 中指定 `android:inputType="textPassword"`,以标识为密码输入。 3. 如果需要自定义图标或颜色,添加额外属性如 `app:passwordToggleDrawable`。 - **示例代码**: ```xml <com.google.android.material.textfield.TextInputLayout android:id="@+id/passwordInputLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="密码" app:passwordToggleEnabled="true" <!-- 启用切换按钮 --> app:passwordToggleTint="@color/black"> <!-- 可选:按钮颜色 --> <EditText android:id="@+id/passwordEditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" /> <!-- 密码输入类型 --> </com.google.android.material.textfield.TextInputLayout> ``` - **效果**:用户输入密码时,右侧会显示眼睛图标;点击图标可切换密码的明文/隐藏状态,提升安全性[^1]。 #### 3. **注意事项** - **依赖版本**:确保在 `build.gradle` 中添加最新 Material Design 依赖(推荐版本 1.6.0 或更高)。例如: ```gradle dependencies { implementation 'com.google.android.material:material:1.9.0' // 使用最新稳定版 } ``` - **兼容性**:`passwordToggleEnabled` 属性需要支持库版本 24 以上,否则可能无效。测试时请使用 Android 5.0 (API 21) 或更高设备。 - **错误处理**:TextInputLayout 还支持错误提示(如 `app:errorEnabled="true"`),可在代码中动态设置错误消息。 - **最佳实践**:结合 ViewModel 或 Data Binding 处理输入验证,确保数据可靠性。 #### 总结 TextInputLayout 简化了表单输入的设计,通过浮动标签和密码切换功能,增强了用户交互。实现时,只需在 XML 中配置属性,无需复杂代码。如果您遇到问题,建议参考 [Android 官方文档](https://material.io/components/text-fields/android) 或社区资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值