您的位置:首页 > 移动开发 > Android开发

快速开发android应用2-使用TextInputLayout实现用户登录及验证

2017-07-07 23:21 1021 查看

概述

本次快速开发Android应用系列,是基于课工场的公开课高效Android工程师6周培养计划,记录微服私访APP的整个开发过程以及当中碰到的问题,供日后学习参考。

上一篇我们主要学习了项目背景以及如何搭建服务端,还没看过前一篇文章的朋友可以先去参考快速开发android应用1-服务器搭建

这是本系列的第二篇,主要实现android客户端的用户登录及验证。其中,使用
TextInputLayout
TextInputEditText
,代替传统的
EditText
来输入用户名和密码。使用
LitePal
代替android原生的
DatabaseHelper
来实现本地数据库用户校验。

本次实现的效果为:



使用TextInputLayout

TextInputLayout
是google推出
Android Masterial Design
原生控件其中之一,Google将UI视觉效果设计得华丽且流畅,同时代码封装更为优雅,开发者只需要在layout.xml中写好布局文件,就可以轻松在手机屏幕上展现出魔法般的动画效果。接下来我们主要看一下如何使用
TextInputLayout
控件以及它和
EditText
的不同点。

添加库依赖

要使用这个控件,需要引入 appcompat-v7 以及 Design Support Library 两个库。

//需改成本地支持的版本
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:design:23.4.0'


布局中的使用

我们必须了解的是,
TextInputLayout
继承于
LinearLayout
,只能拥有一个直接的
ChildView
(类似于 ScrollView ),且这个
ChildView
只能是
EditText


<android.support.design.widget.TextInputLayout
android:id="@+id/il_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginLeft="@dimen/login_text_margin"
android:layout_marginRight="@dimen/login_text_margin">

<android.support.design.widget.TextInputEditText
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/login_name_hint"
android:textSize="@dimen/login_text_size"/>

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


优于EditText的地方

hint漂浮
使用
EditText
时,hint(提示)在点击输入框后会消失;
而使用
InputTextLayout
时不会,它会有一个动画效果,就像漂浮在上方一样,这个就是这个控件的魅力。

错误提示
当我们使用
EditText
对输入的数据合法性、格式等等进行校验,失败时需要给用户提示,这时候需要开发者自己去增加一个View去显示错误结果或者弹出一个提示给用户,无形中增加了开发者的工作量;
而使用
InputTextLayout
检测就方便多了,当数据不合法时,直接通过setError()显示输入错误提示,以及 setErrorEnabled(fasle) 清除错误提示。

/**
* 检测用户名和密码是否符合要求
* @return
*/
private boolean checkUser(String name, String pwd) {
if (TextUtils.isEmpty(name)) {
mUsernameLayout.setError("用户名不能为空");
return false;
}
if (TextUtils.isEmpty(pwd)) {
mPasswordLayout.setError("密码不能为空");
return false;
}
if (pwd.length() < 6 || pwd.length() > 10) {
mPasswordLayout.setError("密码位数要在6到10之间");
return false;
}

return true;
}

private TextWatcher mTextWatcher = 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) {
mUsernameLayout.setErrorEnabled(false);
mPasswordLayout.setErrorEnabled(false);
String pwd = mPasswordText.getText().toString();
//密码位数超限
if (!TextUtils.isEmpty(pwd) && pwd.length() > 10) {
mPasswordLayout.setHint("密码位数不能大于10");
} else {
mPasswordLayout.setHint("请输入密码");
}
}
};
mUsernameText.addTextChangedListener(mTextWatcher);
mPasswordText.addTextChangedListener(mTextWatcher);


其他功能

TextInputLayout输入时,标签和下划线的颜色默认为绿色,可能会和项目的整体颜色不相符,可以通过App Theme 中colorAccent 来指定

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorAccent">#9dd1ee</item>
<item name="textColorError">@color/design_textinput_error_color_light</item>
</style>


可以通过
counterMaxLength
这个属性来指定输入的最大位数,但超出最大位数时,更改错误提示。

<android.support.design.widget.TextInputLayout
android:id="@+id/il_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/login_text_margin"
android:layout_marginRight="@dimen/login_text_margin"
app:counterEnabled="true"
app:counterMaxLength="10">
...

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


TextInputEditText
EditText
都能配合
TextInputLayout
使用。唯一的区别是在横屏且软键盘占满屏幕时,
TextInputEditText
依然能显示提示,而
EditText
的提示会被掩盖。其实看源码就知道,
TextInputEditText
只多一个onCreateInputConnection()方法

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
final InputConnection ic = super.onCreateInputConnection(outAttrs);
if (ic != null && outAttrs.hintText == null) {
// If we don't have a hint and our parent is a TextInputLayout, use it's hint for the
// EditorInfo. This allows us to display a hint in 'extract mode'.
final ViewParent parent = getParent();
if (parent instanceof TextInputLayout) {
outAttrs.hintText = ((TextInputLayout) parent).getHint();
}
}
return ic;
}


使用Litepal存储数据

LitePal是一款开源的Android数据库框架,采用了对象关系映射(ORM)的模式,将平时开发时最常用的一些数据库功能进行了封装,使得数据库业务的开发变得特别简便。

今天主要介绍一下在本项目中如何使用Litepal进行用户的注册和登录的验证,若要详细了解Litepal,请参考附录中郭霖大神的专栏-Android数据库高手秘籍。

配置Litepal

第一步:增加依赖库

dependencies {
compile 'org.litepal.android:core:1.5.1'
}


第二步:将
ChainManagementApp
从继承
Application
改为继承
LitePalApplication
,并做好初始化。

public class ChainManagementApp extends LitePalApplication {
@Override
public void onCreate() {
super.onCreate();
LitePal.initialize(this);
}
}


第三步:创建数据库。

在assets目录下,新建一个Litepal.xml文件,增加如下配置。

<litepal>
<dbname value="chain_management" />
</litepal>


创建User表

Litepal.xml
中配置一个mapping,用于映射
User
对象到数据库中。

<litepal>
...
<list>
<mapping class="com.torch.chainmanage.model.User" />
</list>
</litepal>


创建一个
User
类,继承
DataSupport
,目前暂时只包括用户名
username
和密码
password
两个字段。

public class User extends DataSupport {
private String name;
private String password;

public User() {
}

public User(String name, String password) {
this.name = name;
this.password = password;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}


用户注册

首先,检查用户名和密码是否合法;

其次,通过DataSupport.find()方法查询用户是否存在;

最后,若用户名不存在,则添加此用户到本地数据库中;

/**
* 添加用户
*/
private void addUser(String name, String pwd) {
if(!checkUser(name, pwd)) {
return;
}
//判断用户是否已存在
List<User> userList = DataSupport.where("name = ?", name).find(User.class);
if (userList != null && !userList.isEmpty()) {
showToast("用户名已存在");
return;
}
//加密密码明文
String encryptPwd = MD5Utils.encryptByMD5(pwd);
User user = new User(name, encryptPwd);
if(user.save()) {
showToast("注册成功");
} else {
showToast("注册失败,请重试!!");
}
}


用户登录

首先,检查用户名和密码是否合法;

其次,通过DataSupport.find()方法查询用户是否存在;

最后,若用户名存在,则判断密码是否一致,一致则提示成功,否则提示密码不正确;

private void login(String name, String pwd) {
if(!checkUser(name, pwd)) {
return;
}
//暂时先从本地数据库读取
if(verifyUser(name, pwd)) {
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
}
}

/**
* 用户名验证
* @param name
* @param pwd
*/
private boolean verifyUser(String name, String pwd) {
List<User&
a11f
gt; userList = DataSupport.where("name = ?", name).find(User.class);
if (userList == null || userList.isEmpty()) {
showToast("用户名不存在");
return false;
}
User user = userList.get(0);
String encryptPwd = MD5Utils.encryptByMD5(pwd);
if (!encryptPwd.equals(user.getPassword())) {
showToast("密码错误");
return false;
}
return true;
}


附录

需要源码的请戳这里

参考资料:

郭神的Litepad专栏-Android数据库高手秘籍

Litepal的github地址

Android TextInputLayout,打造 Material Design 风格的文本输入框

使用TextInputLayout所遇到的坑-java.lang.UnsupportedOperationException: Failed to resolve attribute at index
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐