首页 > 编程语言 > Android自定义控件实现通用验证码输入框
2021
01-29

Android自定义控件实现通用验证码输入框

本文为大家分享了Android实现通用验证码输入框的具体代码,供大家参考,具体内容如下

效果图

话不多说先上效果图,可以先先看看是不是自己想要的

闲聊

闲来无事优化项目时,发现原来的验证码输入框,可扩展性不高,就拿来优化了一下,说说我开始的的思路吧,最开始是想用自定义View实现的,但是发现各种画矩,太烦人了,最后采用的组合控件的形式,Android有现成的控件,用来组合组合就能用,为什么不用呢。

源码

xml ITEM 布局文件(view_auth_code_input_item.xml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 
 <TextView
  android:id="@+id/number_tv"
  style="@style/TextStyleMain"
  android:layout_width="match_parent"
  android:layout_height="0mm"
  android:layout_weight="1"
  android:maxLength="1"
  android:text="0"
  android:textSize="72mm" />
 
 <View
  android:id="@+id/split_v"
  android:layout_width="match_parent"
  android:layout_height="1mm"
  android:background="@color/colorMain" />
 
</LinearLayout>

attrs 自定义属性(attrs.xml)

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
<?xml version="1.0" encoding="utf-8"?>
<resources>
 
 <!-- 自定义验证码输入框 属性 -->
 <declare-styleable name="AuthCodeInputView">
  <!-- 当前输入位分割线颜色 -->
  <attr name="currentSplitLineColor"
   format="reference|color" />
  <!-- 其他输入位分割线颜色 -->
  <attr name="otherSplitLineColor"
   format="reference|color" />
  <!-- 分割线高度 -->
  <attr name="splitLineHeight"
   format="dimension" />
  <!-- 验证码位数 -->
  <attr name="digit"
   format="integer" />
  <!-- 单个验证码宽度 -->
  <attr name="singleCaptchaWidth"
   format="dimension" />
  <!-- 验证码当前输入位字体颜色 -->
  <attr name="currentTextColor"
   format="reference|color" />
  <!-- 验证码当前输入位字体大小 -->
  <attr name="currentTextSize"
   format="dimension" />
  <!-- 验证码其他输入位字体颜色 -->
  <attr name="otherTextColor"
   format="reference|color" />
  <!-- 验证码其它输入位字体大小 -->
  <attr name="otherTextSize"
   format="dimension" />
  <!-- 默认颜色 -->
  <attr name="defaultColor"
   format="reference|color" />
  <!-- 默认字体大小 -->
  <attr name="defaultTextSize"
   format="dimension" />
  <!-- 默认间距 -->
  <attr name="defaultSpacing"
   format="dimension" />
 </declare-styleable>
 
</resources>

组合控件(AuthCodeInputView.java)

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
 
import androidx.annotation.ColorInt;
import androidx.annotation.RequiresApi;
 
/**
 * <pre>
 *  <b>author</b> :BraveTou
 *  <b>blog</b>  :https://blog.csdn.net/bravetou
 *  <b>time</b>  :2020/9/4 16:43
 *  <b>desc</b>  :<pre>
 *   自定义验证码输入框
 *  </pre>
 * </pre>
 */
public class AuthCodeInputView extends LinearLayout {
 // <!-- 默认间距 -->
 private int mDefaultSpacing = 16;
 // <!-- 默认颜色 -->
 @ColorInt
 private int mDefaultColor = Color.BLACK;
 // <!-- 默认字体大小 -->
 private int mDefaultTextSize = 36;
 // <!-- 当前输入位分割线颜色 -->
 @ColorInt
 private int mCurrentSplitLineColor = mDefaultColor;
 // <!-- 其他输入位分割线颜色 -->
 @ColorInt
 private int mOtherSplitLineColor = mDefaultColor;
 // <!-- 分割线高度 -->
 private int mSplitLineHeight = 1;
 // <!-- 验证码位数 -->
 private int mDigit = 4;
 // <!-- 单个验证码宽度 -->
 private int mSingleCaptchaWidth = 100;
 // <!-- 验证码当前输入位字体颜色 -->
 @ColorInt
 private int mCurrentTextColor = mDefaultColor;
 // <!-- 验证码当前输入位字体大小 -->
 private int mCurrentTextSize = mDefaultTextSize;
 // <!-- 验证码其他输入位字体颜色 -->
 @ColorInt
 private int mOtherTextColor = mDefaultColor;
 // <!-- 验证码其它输入位字体大小 -->
 private int mOtherTextSize = mDefaultTextSize;
 
 // 记录当前输入文本
 private String mText = "";
 
 public AuthCodeInputView(Context context) {
  super(context);
  init(context, null);
 }
 
 public AuthCodeInputView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init(context, attrs);
 }
 
 public AuthCodeInputView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init(context, attrs);
 }
 
 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
 public AuthCodeInputView(Context context, AttributeSet attrs, int defStyleAttr,
        int defStyleRes) {
  super(context, attrs, defStyleAttr, defStyleRes);
  init(context, attrs);
 }
 
 // 初始化
 private void init(Context context, AttributeSet attrs) {
  setOrientation(LinearLayout.HORIZONTAL);
  setGravity(Gravity.CENTER);
  if (getChildCount() > 0) {
   removeAllViews();
  }
  initAttrs(context, attrs);
  if (mDigit <= 0) {
   return;
  }
  for (int i = 0; i < mDigit; i++) {
   // 实例化 ITEM 组件
   View child = LayoutInflater.from(context).inflate(
     R.layout.view_auth_code_input_item, this, false);
   LayoutParams lp = new LayoutParams(mSingleCaptchaWidth,
     ViewGroup.LayoutParams.MATCH_PARENT);
   if (i != 0) {
    lp.leftMargin = mDefaultSpacing;
   }
   child.setLayoutParams(lp);
   setViewAttrs(child, null, false);
   // 分割线高度只在初始化时设置一次
   View mSplitV = child.findViewById(R.id.split_v);
   LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
     ViewGroup.LayoutParams.MATCH_PARENT, mSplitLineHeight);
   mSplitV.setLayoutParams(params);
   addView(child);
  }
 }
 
 // 设置(未)选中属性
 private void setViewAttrs(View child, String text, boolean isSelected) {
  TextView mNumberTv = child.findViewById(R.id.number_tv);
  View mSplitV = child.findViewById(R.id.split_v);
  if (isSelected) {
   mNumberTv.setTextColor(mCurrentTextColor);
   mNumberTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, mCurrentTextSize);
   mSplitV.setBackgroundColor(mCurrentSplitLineColor);
  } else {
   mNumberTv.setTextColor(mOtherTextColor);
   mNumberTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, mOtherTextSize);
   mSplitV.setBackgroundColor(mOtherSplitLineColor);
  }
  mNumberTv.setText(TextUtils.isEmpty(text) ? "" : text);
 }
 
 // 初始化属性
 private void initAttrs(Context context, AttributeSet attrs) {
  if (null != attrs) {
   // AttributeSet 属性值的索引
   TypedArray o = context.obtainStyledAttributes(attrs, R.styleable.AuthCodeInputView);
   // 默认间距
   mDefaultSpacing = (int) o.getDimension(R.styleable.AuthCodeInputView_defaultSpacing,
     16f);
   // 获取默认颜色
   mDefaultColor = o.getColor(R.styleable.AuthCodeInputView_defaultColor, Color.BLACK);
   // 获取默认字体大小
   mDefaultTextSize = (int) o.getDimension(R.styleable.AuthCodeInputView_defaultTextSize
     , 36f);
   // 输入位分割线颜色
   mCurrentSplitLineColor =
     o.getColor(R.styleable.AuthCodeInputView_currentSplitLineColor, mDefaultColor);
   // 其他输入位分割线颜色
   mOtherSplitLineColor = o.getColor(R.styleable.AuthCodeInputView_otherSplitLineColor,
     mDefaultColor);
   // 分割线高度
   mSplitLineHeight = (int) o.getDimension(R.styleable.AuthCodeInputView_splitLineHeight
     , 1f);
   mSplitLineHeight = mSplitLineHeight <= 1 ? 1 : mSplitLineHeight;
   // 验证码位数
   mDigit = o.getInteger(R.styleable.AuthCodeInputView_digit, 4);
   // 单个验证码宽度
   mSingleCaptchaWidth =
     (int) o.getDimension(R.styleable.AuthCodeInputView_singleCaptchaWidth, 100f);
   // 验证码当前输入位字体颜色
   mCurrentTextColor = o.getColor(R.styleable.AuthCodeInputView_currentTextColor,
     mDefaultColor);
   // 验证码当前输入位字体大小
   mCurrentTextSize = (int) o.getDimension(R.styleable.AuthCodeInputView_currentTextSize
     , mDefaultTextSize);
   // 验证码其他输入位字体颜色
   mOtherTextColor = o.getColor(R.styleable.AuthCodeInputView_otherTextColor,
     mDefaultColor);
   // 验证码其它输入位字体大小
   mOtherTextSize = (int) o.getDimension(R.styleable.AuthCodeInputView_otherTextSize,
     mDefaultTextSize);
   // 回收资源
   o.recycle();
  }
 }
 
 // 追加文本
 public void addText(String text) {
  text = TextUtils.isEmpty(text) ? "" : text;
  setText(mText + text);
 }
 
 // 删除文本
 public void delText() {
  int count = TextUtils.isEmpty(mText) ? 0 : mText.length();
  if (count > 0) {
   setText(mText.substring(0, count - 1));
  } else {
   setText("");
  }
 }
 
 // 设置文本
 public void setText(String text) {
  text = text.trim();
  int length = TextUtils.isEmpty(text) ? 0 : text.length();
  if (length > mDigit) {
   this.mText = text.substring(0, mDigit);
   length = mDigit;
  } else {
   this.mText = length > 0 ? text : "";
  }
  int count = getChildCount();
  for (int i = 0; i < count; i++) {
   View child = getChildAt(i);
   if (i + 1 < length) {
    setViewAttrs(child, String.valueOf(text.charAt(i)), false);
   } else if (i + 1 == length) {
    setViewAttrs(child, String.valueOf(text.charAt(i)), true);
   } else {
    setViewAttrs(child, null, false);
   }
  }
 }
 
 // 获取文本
 public String getText() {
  return mText;
 }
}

至于效果图下面那个安全键盘源码就太多了,我就不多了的,我这边是组合控件实现的,超简单。

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

编程技巧