之前公司有过需求,要求做一个类似滴滴打车输入验证码的页面,长这样:
emmmmmm,好像截了iOS的图,不要在意这些细节。
来分析一下这个验证码部分,实现这样一个自定义View,首先,要区分单个验证码选中状态和未选中状态,并且光标悬停在选中的验证码中心,其次, 每次输入文字后需要依次显示在每个单独的验证码容器中,还有诸如自定义验证码选中状态、清空输入验证码等等。受到博文Android 自定义View之带密码模式的正方形验证码输入框的启发,我决定使用继承RelativeLayout的方式来完成这个自定义View。
实现思路
笔者这里决定继承RelativeLayout来实现自定义验证码的功能。显示验证码可以使用几个TextView,这里需要将TextView统一管理,所以还需要一个TextView数组。有光标,那自然而然的就想到了EditText,可以使用一个透明背景的EditText。几个验证码可以使用TextView以一定的规则进行排列,通过监听EditText的输入,拦截到输入字符,并将字符传递给TextView数组,并将EditText置为空,同时重设TextView选中状态,移动EditText光标。笔者这里采用给EditText设置paddingLeft的方式来实现光标的移动,当然,需要经过一些计算。OK,大概思路就是这样了,具体的代码我们继续看下面的。
具体实现
首先,我们需要一个类来继承RelativeLayout,并且给这个类分配上一些自定义属性,在attrs.xml文件中定义以下属性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 自定义验证码-->
<declare-styleable name="VerificationCodeView">
<!--输入框的数量-->
<attr name="vcv_code_number" format="integer" />
<!--单个验证码的宽度-->
<attr name="vcv_code_width" format="dimension|reference" />
<!--输入框文字颜色-->
<attr name="vcv_code_color" format="color|reference" />
<!--输入框文字大小-->
<attr name="vcv_code_size" format="dimension|reference" />
<!--输入框获取焦点时边框-->
<attr name="vcv_code_bg_focus" format="reference" />
<!--输入框没有焦点时边框-->
<attr name="vcv_code_bg_normal" format="reference" />
</declare-styleable>
</resources>
具体属性都再代码中注释出来了,接着,在Java类中取出这些属性:
/**
* @author 小米Xylitol
* @email xiaomi987@hotmail.com
* @desc Android验证码View
* @date 2018-05-09 10:25
*/
public class VerificationCodeView extends RelativeLayout {
//当前验证码View用来展示验证码的TextView数组,数组个数由codeNum决定
private TextView[] textViews;
//用来输入验证码的EditText输入框,输入框会跟随输入个数移动,显示或者隐藏光标等
private WiseEditText editText;
//当前验证码View展示验证码个数
private int codeNum;
//每个Text