服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android自定义方框EditText注册验证码

Android自定义方框EditText注册验证码

2022-02-28 15:37Xia_焱 Android

这篇文章主要为大家详细介绍了Android自定义方框EditText注册验证码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

先来个效果图让大家看一看,现在好多app都用类似的注册页

Android自定义方框EditText注册验证码

实现思路

  • 用一个透明的EditText与四个TextView重叠,并给TextView设置默认背景
  • 第4个TextView输入完成后,要设置回调,并且要加入增加删除的回调
  • 还要监听EditText内容的变化,获取内容,并且改变EditText下面的TextView的颜色
  • 重新发送的是采用一个自定义的CountDownTimer类
  • 弹出效果自定义的一个Dialog继承DialogFragment

自定义EditText的布局

?
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
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="wrap_content">
 
 <LinearLayout
  android:layout_width="wrap_content"
  android:layout_height="47dp"
  android:gravity="center"
  android:orientation="horizontal"
  android:weightSum="3">
 
 
  <TextView
   android:id="@+id/item_code_iv1"
   style="@style/text_editStyle" />
 
  <View
   android:layout_width="0dp"
   android:layout_height="wrap_content"
   android:layout_weight="1" />
 
  <TextView
   android:id="@+id/item_code_iv2"
   style="@style/text_editStyle" />
 
  <View
   android:layout_width="0dp"
   android:layout_height="wrap_content"
   android:layout_weight="1" />
 
  <TextView
   android:id="@+id/item_code_iv3"
   style="@style/text_editStyle" />
 
  <View
   android:layout_width="0dp"
   android:layout_height="wrap_content"
   android:layout_weight="1" />
 
  <TextView
   android:id="@+id/item_code_iv4"
   style="@style/text_editStyle" />
 
 
 </LinearLayout>
 
 <EditText
  android:id="@+id/item_edittext"
  android:layout_width="match_parent"
  android:layout_height="47dp"
  android:background="@android:color/transparent"
  android:inputType="number" />
</RelativeLayout>

style

?
1
2
3
4
5
6
7
8
9
<style name="text_editStyle" >
  <item name="android:layout_height">47dp</item>
  <item name="android:layout_width">47dp</item>
  <item name="android:background">@mipmap/bg_verify</item>
  <item name="android:gravity">center</item>
  <item name="android:textColor">@color/common_blue_0090FF</item>
  <item name="android:textSize">18sp</item>
 
</style>

View的代码

?
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
private EditText editText;
 private TextView[] TextViews;
 private StringBuffer stringBuffer = new StringBuffer();
 private int count = 4;
 private String inputContent;
 
 public SecurityCodeView(Context context) {
  this(context, null);
 }
 
 public SecurityCodeView(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }
 
 public SecurityCodeView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  TextViews = new TextView[4];
  View.inflate(context, R.layout.view_security_code, this);
 
  editText = (EditText) findViewById(R.id.item_edittext);
  TextViews[0] = (TextView) findViewById(R.id.item_code_iv1);
  TextViews[1] = (TextView) findViewById(R.id.item_code_iv2);
  TextViews[2] = (TextView) findViewById(R.id.item_code_iv3);
  TextViews[3] = (TextView) findViewById(R.id.item_code_iv4);
 
  editText.setCursorVisible(false);//将光标隐藏
  setListener();
 }
 
 /**
  * 清空输入内容
  */
 public void clearEditText() {
  stringBuffer.delete(0, stringBuffer.length());
  inputContent = stringBuffer.toString();
  for (int i = 0; i < TextViews.length; i++) {
   TextViews[i].setText("");
   TextViews[i].setBackgroundResource(R.mipmap.bg_verify);
  }
 }
 
 private InputCompleteListener inputCompleteListener;
 
 public void setInputCompleteListener(InputCompleteListener inputCompleteListener) {
  this.inputCompleteListener = inputCompleteListener;
 }
 
 public interface InputCompleteListener {
  void inputComplete();
 
  void deleteContent(boolean isDelete);
 }
 
 /**
  * 获取输入文本
  *
  * @return
  */
 public String getEditContent() {
  return inputContent;
}

监听代码

?
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
private void setListener() {
 editText.addTextChangedListener(new TextWatcher() {
 
  @Override
  public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
 
  }
 
  @Override
  public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
 
  }
 
  @Override
  public void afterTextChanged(Editable editable) {
   //重点 如果字符不为""时才进行操作
   if (!editable.toString().equals("")) {
    if (stringBuffer.length() > 3) {
     //当文本长度大于3位时edittext置空
     editText.setText("");
     return;
    } else {
     //将文字添加到StringBuffer中
     stringBuffer.append(editable);
     editText.setText("");//添加后将EditText置空 造成没有文字输入的错局
     // Log.e("TAG", "afterTextChanged: stringBuffer is " + stringBuffer);
     count = stringBuffer.length();//记录stringbuffer的长度
     inputContent = stringBuffer.toString();
     if (stringBuffer.length() == 4) {
      //文字长度位4 则调用完成输入的监听
      if (inputCompleteListener != null) {
       inputCompleteListener.inputComplete();
      }
     }
    }
 
    for (int i = 0; i < stringBuffer.length(); i++) {
     TextViews[i].setText(String.valueOf(inputContent.charAt(i)));
     TextViews[i].setBackgroundResource(R.mipmap.bg_verify_press);
    }
 
   }
  }
 });
 
 editText.setOnKeyListener(new OnKeyListener() {
  @Override
  public boolean onKey(View v, int keyCode, KeyEvent event) {
   if (keyCode == KeyEvent.KEYCODE_DEL
     && event.getAction() == KeyEvent.ACTION_DOWN) {
    if (onKeyDelete()) return true;
    return true;
   }
   return false;
  }
 });
}
 
 
public boolean onKeyDelete() {
 if (count == 0) {
  count = 4;
  return true;
 }
 if (stringBuffer.length() > 0) {
  //删除相应位置的字符
  stringBuffer.delete((count - 1), count);
  count--;
  // Log.e(TAG, "afterTextChanged: stringBuffer is " + stringBuffer);
  inputContent = stringBuffer.toString();
  TextViews[stringBuffer.length()].setText("");
  TextViews[stringBuffer.length()].setBackgroundResource(R.mipmap.bg_verify);
  if (inputCompleteListener != null)
   inputCompleteListener.deleteContent(true);//有删除就通知manger
 
 }
 return false;
}

自定义的EditText到这了算是结束了

弹出框的布局

?
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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/activity_main"
 android:layout_width="283dp"
 android:layout_height="273dp"
 android:layout_gravity="center"
 android:layout_marginBottom="50dp"
 android:background="@mipmap/bg_view1"
 android:orientation="vertical">
 
 <include layout="@layout/layout_titile" />
 
 <com.example.admin.myapplication.SecurityCodeView
  android:id="@+id/scv_edittext"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_gravity="center_horizontal"
  android:layout_marginLeft="20dp"
  android:layout_marginRight="20dp"
  android:layout_marginTop="35dp" />
 
 <TextView
  android:id="@+id/tv_text"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_marginLeft="20dp"
  android:layout_marginRight="20dp"
  android:layout_marginTop="13dp"
  android:text="输入验证码表示同意《用户协议》" />
 
 <LinearLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_marginBottom="25dp"
  android:layout_marginTop="3dp"
  android:orientation="horizontal">
 
  <TextView
 
   android:id="@+id/tv_phone"
   android:layout_width="0dp"
   android:layout_height="wrap_content"
   android:layout_marginLeft="20dp"
   android:layout_marginRight="20dp"
   android:layout_marginTop="13dp"
   android:layout_weight="1"
   android:text="电话" />
 
  <TextView
   android:id="@+id/tv_click"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_marginLeft="20dp"
   android:layout_marginRight="20dp"
   android:layout_marginTop="13dp"
   android:text="重新发送"
   android:textColor="@color/colorPrimary" />
 </LinearLayout>
 
 
</LinearLayout>

[大体的思路,点击事件之后弹出一个Dialog,然后再这个页面进行注册,有可能这个Dialog会复用,或者改一些样式(采用Builder设计模式)]

接下来自定义Dialog

要实现EditText的两个接口

?
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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
public class XyAlertDialog extends DialogFragment implements SecurityCodeView.InputCompleteListener {
 private SecurityCodeView editText;
 private TextView text;
 private TextView tv_title;
 private ImageView img_close;
 public static final String TAG = XyAlertDialog.class.getSimpleName();
 private Builder builder;
 private static XyAlertDialog instance = new XyAlertDialog();
 private TextView tv_phone;
 private TextView tv_click;
 
 public static XyAlertDialog getInstance() {
  return instance;
 }
 
 @Override
 public void onCreate(@Nullable Bundle savedInstanceState) {
  this.setCancelable(true);
  setRetainInstance(true);
  super.onCreate(savedInstanceState);
 
  if (savedInstanceState != null) {
   try {
    if (isAdded() && getActivity() != null)
     if (builder != null)
      builder = (Builder) savedInstanceState.getSerializable(Builder.class.getSimpleName());
   } catch (Exception e) {
   }
 
  }
 }
 
 @Override
 public void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  try {
   if (isAdded() && getActivity() != null)
    if (builder != null)
     outState.putSerializable(Builder.class.getSimpleName(), builder);
  } catch (Exception e) {
   Log.d(TAG, e.toString());
  }
 }
 
 @NonNull
 @Override
 public Dialog onCreateDialog(Bundle savedInstanceState) {
  Dialog dialog = super.onCreateDialog(savedInstanceState);
  dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
  dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
  dialog.setCanceledOnTouchOutside(false);//点击旁白不消失
  return dialog;
 }
 
 @Nullable
 @Override
 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup
   container, @Nullable Bundle savedInstanceState) {
  return inflater.inflate(R.layout.activity_xia, container, false);
 }
 
 @Override
 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
  super.onViewCreated(view, savedInstanceState);
  initViews(view);
 
 }
 
 private Dialog show(Activity activity, Builder builder) {
  this.builder = builder;
  if (!isAdded())
   show(((AppCompatActivity) activity).getSupportFragmentManager(), TAG);
  return getDialog();
 }
 
 private void initViews(View view) {
  tv_title = (TextView) view.findViewById(R.id.tv_title);
  img_close = (ImageView) view.findViewById(R.id.img_close);
  editText = (SecurityCodeView) view.findViewById(R.id.scv_edittext);
  text = (TextView) view.findViewById(R.id.tv_text);
  tv_phone = (TextView) view.findViewById(R.id.tv_phone);
  tv_click = (TextView) view.findViewById(R.id.tv_click);
  editText.setInputCompleteListener(this);
  tv_phone.setText(builder.getTextTitle());
  img_close.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    dismiss();
   }
  });
  tv_click.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    CountDownTimerUtils mCountDownTimerUtils = new CountDownTimerUtils(tv_click, 60000, 1000);
    mCountDownTimerUtils.start();
   }
  });
 }
 
 public static class Builder implements Serializable {
 
  private String positiveButtonText;
  private String negativeButtonText;
  private String textTitle;
  private String body;
 
  private OnPositiveClicked onPositiveClicked;
  private OnNegativeClicked onNegativeClicked;
  private boolean autoHide;
  private int timeToHide;
  private int positiveTextColor;
  private int backgroundColor;
  private int negativeColor;
  private int titleColor;
  private int bodyColor;
  private Typeface titleFont;
  private Typeface bodyFont;
  private Typeface positiveButtonFont;
  private Typeface negativeButtonFont;
 
  private Typeface alertFont;
  private Context context;
  private PanelGravity buttonsGravity;
 
  public PanelGravity getButtonsGravity() {
   return buttonsGravity;
  }
 
  public Builder setButtonsGravity(PanelGravity buttonsGravity) {
   this.buttonsGravity = buttonsGravity;
   return this;
  }
 
  public Typeface getAlertFont() {
   return alertFont;
  }
 
  public Builder setAlertFont(String alertFont) {
   this.alertFont = Typeface.createFromAsset(context.getAssets(), alertFont);
   return this;
  }
 
  public Typeface getPositiveButtonFont() {
   return positiveButtonFont;
  }
 
  public Builder setPositiveButtonFont(String positiveButtonFont) {
   this.positiveButtonFont = Typeface.createFromAsset(context.getAssets(), positiveButtonFont);
   return this;
  }
 
  public Typeface getNegativeButtonFont() {
   return negativeButtonFont;
  }
 
  public Builder setNegativeButtonFont(String negativeButtonFont) {
   this.negativeButtonFont = Typeface.createFromAsset(context.getAssets(), negativeButtonFont);
   return this;
  }
 
  public Typeface getTitleFont() {
   return titleFont;
  }
 
 
  public Builder setTitleFont(String titleFontPath) {
   this.titleFont = Typeface.createFromAsset(context.getAssets(), titleFontPath);
   return this;
  }
 
  public Typeface getBodyFont() {
   return bodyFont;
  }
 
  public Builder setBodyFont(String bodyFontPath) {
   this.bodyFont = Typeface.createFromAsset(context.getAssets(), bodyFontPath);
   return this;
  }
 
 
  public int getTimeToHide() {
   return timeToHide;
  }
 
  public Builder setTimeToHide(int timeToHide) {
   this.timeToHide = timeToHide;
   return this;
  }
 
  public boolean isAutoHide() {
   return autoHide;
  }
 
  public Builder setAutoHide(boolean autoHide) {
   this.autoHide = autoHide;
   return this;
  }
 
  public Context getContext() {
   return context;
  }
 
  public Builder setActivity(Context context) {
   this.context = context;
   return this;
  }
 
  public Builder(Context context) {
   this.context = context;
  }
  public void setCancelable(boolean flag) {
   throw new RuntimeException("Stub!");
  }
 
  public int getPositiveTextColor() {
   return positiveTextColor;
  }
 
  public Builder setPositiveColor(int positiveTextColor) {
   this.positiveTextColor = positiveTextColor;
   return this;
  }
 
 
  public int getBackgroundColor() {
   return backgroundColor;
  }
 
  public Builder setBackgroundColor(int backgroundColor) {
   this.backgroundColor = backgroundColor;
   return this;
  }
 
  public int getNegativeColor() {
   return negativeColor;
  }
 
  public Builder setNegativeColor(int negativeColor) {
   this.negativeColor = negativeColor;
   return this;
  }
 
 
  public int getTitleColor() {
   return titleColor;
  }
 
  public Builder setTitleColor(int titleColor) {
   this.titleColor = titleColor;
   return this;
  }
 
  public int getBodyColor() {
   return bodyColor;
  }
 
  public Builder setBodyColor(int bodyColor) {
   this.bodyColor = bodyColor;
   return this;
  }
 
  public String getPositiveButtonText() {
   return positiveButtonText;
  }
 
 
  public Builder setPositiveButtonText(int positiveButtonText) {
   this.positiveButtonText = context.getString(positiveButtonText);
   return this;
  }
 
  public Builder setPositiveButtonText(String positiveButtonText) {
   this.positiveButtonText = positiveButtonText;
   return this;
  }
 
  public String getNegativeButtonText() {
   return negativeButtonText;
  }
 
  public Builder setNegativeButtonText(String negativeButtonText) {
   this.negativeButtonText = negativeButtonText;
   return this;
  }
 
  public Builder setNegativeButtonText(int negativeButtonText) {
   this.negativeButtonText = context.getString(negativeButtonText);
   return this;
  }
 
  public String getTextTitle() {
   return textTitle;
  }
 
  public Builder setTextTitle(String textTitle) {
   this.textTitle = textTitle;
   return this;
  }
 
  public Builder setTextTitle(int textTitle) {
   this.textTitle = context.getString(textTitle);
   return this;
  }
 
  public String getBody() {
   return body;
  }
 
  public Builder setBody(String body) {
   this.body = body;
   return this;
  }
 
  public Builder setBody(int body) {
   this.body = context.getString(body);
   return this;
  }
 
  public OnPositiveClicked getOnPositiveClicked() {
   return onPositiveClicked;
  }
 
  public Builder setOnPositiveClicked(OnPositiveClicked onPositiveClicked) {
   this.onPositiveClicked = onPositiveClicked;
   return this;
  }
 
  public OnNegativeClicked getOnNegativeClicked() {
   return onNegativeClicked;
  }
 
  public Builder setOnNegativeClicked(OnNegativeClicked onNegativeClicked) {
   this.onNegativeClicked = onNegativeClicked;
   return this;
  }
 
 
  public Builder build() {
   return this;
  }
 
 
  public Dialog show() {
   return XyAlertDialog.getInstance().show(((Activity) context), this);
  }
 
 }
 
 
 @Override
 public void onPause() {
  if (isAdded() && getActivity() != null) {
   builder = null;
  }
  super.onPause();
 }
 
 public interface OnPositiveClicked {
  void OnClick(View view, Dialog dialog);
 }
 
 public interface OnNegativeClicked {
  void OnClick(View view, Dialog dialog);
 }
 
 public enum PanelGravity {
  LEFT,
  RIGHT,
  CENTER
 }
//EditText的接口
 @Override
 public void inputComplete() {
  if (!editText.getEditContent().equals("1234")) {
   text.setText("验证码输入错误");
   text.setTextColor(Color.RED);
  }
 }
 
 @Override
 public void deleteContent(boolean isDelete) {
  if (isDelete) {
   text.setText("输入验证码表示同意《用户协议》");
   text.setTextColor(Color.BLACK);
  }
 }
}

至于那个自定义的CountDownTimer在这里有介绍

Android实现点击获取验证码60秒后重新获取功能

源码地址:Android自定义方框EditText注册验证码

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

原文链接:https://blog.csdn.net/macaopark/article/details/69061502

延伸 · 阅读

精彩推荐