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

概述

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

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

这是本系列的第二篇,主要实现android客户端的用户登录及验证。其中,使用TextInputLayoutTextInputEditText,代替传统的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的地方

  1. hint漂浮
    使用EditText时,hint(提示)在点击输入框后会消失;
    而使用InputTextLayout时不会,它会有一个动画效果,就像漂浮在上方一样,这个就是这个控件的魅力。
  2. 错误提示
    当我们使用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>
  • TextInputEditTextEditText都能配合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> 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;
    }

附录

需要源码的请戳这里


参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值