Android使用TextInputLayout创建登陆页面

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

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

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

在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文件中,添加如下依赖:

  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。下面是布局的样子:

<LinearLayout xmlns: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文件:

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

第四步: 使用TextInputLayout

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

  <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输入框做同样的事情。

  <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视图的引用。

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

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

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

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

2. 处理错误

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

第一步: 实现 onClick 方法

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

  btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      // STUB
    }
  });

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

  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 上关于邮箱验证的指导,写了如下的正则表达式

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

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

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

  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个字符。

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

第三步: 获取数据

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

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方法的实现就很简单了。

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方法,但是目前它是空的因为这超出了本教程的范围。

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 到主题以改变表单的颜色。

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

总结

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android文本输入框(EditText)输入密码时显示与隐藏

    代码很简单,这里就不多废话了. 复制代码 代码如下: package cc.c; import android.app.Activity; import android.os.Bundle; import android.text.Selection; import android.text.Spannable; import android.text.method.HideReturnsTransformationMethod; import android.text.method.Passw

  • Android软键盘挡住输入框的终极解决方案

    前言 开发做得久了,总免不了会遇到各种坑. 而在Android开发的路上,『软键盘挡住了输入框』这个坑,可谓是一个旷日持久的巨坑--来来来,我们慢慢看. 入门篇 最基本的情况,如图所示:在页面底部有一个EditText,如果不做任何处理,那么在软键盘弹出的时候,就有可能会挡住EditText. 对于这种情况的处理其实很简单,只需要在AndroidManifest文件中对activity设置:android:windowSoftInputMode的值adjustPan或者adjustResize即

  • Android 仿支付宝密码输入框效果

    模仿支付宝输入效果,实现很简单,就是画个矩形框和圆形,其他的通过组合view来实现所有功能,虽然简单但是封装起来,方便以后使用,也分享一下,希望对别人也有点帮助. 1.如何使用,可以设置自己的进入退出动画,不设置则没有动画效果,自己觉得封装之后还是非常用好的. private MyInputPwdUtil myInputPwdUtil; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(sa

  • android仿支付宝、微信密码输入框效果

    本文实例为大家分享了android密码输入框效果展示的具体代码,供大家参考,具体内容如下 老规矩,先看效果:这是现在商城类app中很常见的支付密码效果,首先说下这个不是自定义控件,是github上的开源库: https://github.com/Jungerr/GridPasswordView 下面主要说下这个开源库的用法和平时我们常用的几点功能: 想要使用这个开源库首先我们需要将库导入到咱们的项目中: 直接在app的build.gradle下添加如下代码 dependencies { comp

  • Android输入法弹出时覆盖输入框问题的解决方法

    当一个activity中含有输入框时,我们点击输入框,会弹出输入法界面,整个界面的变化效果与manifest中对应设置的android:windowSoftInputMode属性有关,一般可以设置的值如下, <activity android:windowSoftInputMode=[ "stateUnspecified", "stateUnchanged", "stateHidden", "stateAlwaysHidden&q

  • TextInputLayout输入框控件的悬浮标签

    本文实例为大家分享了TextInputLayout输入框悬浮标签的具体代码,供大家参考,具体内容如下 TextInputLayout也是5.0以后的效果,想要使用同样需要在build中配置: dependencies { compile 'com.android.support:design:23.3.0' } TextInputLayout可以用来显示一个提示错误信息,把Hint放到EditText左上方等效果的一个布局: 如果项目中有这类的需求,使用TextInputLayout实现起来非常

  • Android UI设计系列之自定义EditText实现带清除功能的输入框(3)

    最近公司的产品在陆续做升级,上级领导给的任务是优化代码结构以及项目架构,力争把项目写的精巧简练,于是我们满工程找冗余... 我们都知道每一个项目基本上都是有登陆页的,在登陆页中肯定是少不了输入框了,当我们在输入框中输入数据后如果输入的内容不正确或者是错误的或者是想重新输入,如果嗯键盘上的删除键就得一个一个的去删除,这时候我们或许就想要是能有一个标记当点击了这个标记能把我们刚刚输入的内容清空就好了.这样可以极大的提升用户体验,就拿QQ的登陆来说吧,效果如下: 当点击密码框右侧的小×图标时输入的内容

  • android输入框与文本框加滚动条scrollview示例

    我们都知道EditText与TextView是Android的文本输入框和文本显示框,但是基于手机屏幕的大小因素,如果在需要输入较多文字或者显示较多内容的时候,手机屏幕是远远不够的,因此让文本框具有滚动条的功能是手机上必备的,要加上滚动条,其实很简单,只需要在文本输入框或者文本显示框上面加上滚动条控件即可,该控件名字为ScrollView,以下我们对比下(以TextView举例). 复制代码 代码如下: //A.未加滚动效果 <TextView android:layout_width="

  • Android实现动态显示或隐藏密码输入框的内容

    本文实例展示了Android实现动态显示或隐藏密码输入框内容的方法,分享给大家供大家参考之用.具体方法如下: 该功能可通过设置EditText的setTransformationMethod()方法来实现隐藏密码或者显示密码. 示例代码如下: private Button mBtnPassword; private EditText mEtPassword; private boolean mbDisplayFlg = false; /** Called when the activity is

  • android仿微信支付宝的支付密码输入框示例

    大家好,我是狸小华,萌汉子一枚.今天给大家带来的是仿微信/支付宝的密码输入框.这个效果也出来有一段时间了,所以搜索一下还是有不少的网友实现,但是,但是!经过一番查看后,我发现他们的实现分为两大类. 一,直接继承EditText,然后在ondraw里面做文章:二,EditText外面包一个viewGroup.我不喜欢这两种实现方式,觉着有些臃肿了,所以我详细介绍下我的实现方式:直接继承View,获取用户的输入,然后draw出来. 我们实现的是上面的密码输入框,这个键盘...系统自带的哦,调用用户输

  • android仿支付宝密码输入框效果

    本文实例为大家分享了android仿支付宝密码输入框展示的具体代码,供大家参考,具体内容如下 这个没什么好分析的,就是一些基本的绘制什么线,矩形什么的,看代码更具体 布局文件: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layou

随机推荐