先上两张效果图:
1.java类:
package com...ui;import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;import com...R;import java.lang.reflect.Field;/*** @ClassName: VerificationCodeView* @Desciption: //自定义验证码输入框view* @author: jesse_android* @date: 2018-03-29*/public class VerificationCodeView extends LinearLayout implements TextWatcher, View.OnKeyListener, View.OnFocusChangeListener {private Context mContext;private long endTime = 0;private OnCodeFinishListener onCodeFinishListener;/*** 输入框数量*/private int mEtNumber;/*** 输入框类型*/private VCInputType mEtInputType;/*** 输入框的宽度*/private int mEtWidth;/*** 输入框的高度*/private int mEtHeight;/*** 文字颜色*/private int mEtTextColor;/*** 文字大小*/private float mEtTextSize;/*** 输入框背景*/private int mEtTextBg;private int mCursorDrawable;public OnCodeFinishListener getOnCodeFinishListener() {return onCodeFinishListener;}public void setOnCodeFinishListener(OnCodeFinishListener onCodeFinishListener) {this.onCodeFinishListener = onCodeFinishListener;}public int getmEtNumber() {return mEtNumber;}public void setmEtNumber(int mEtNumber) {this.mEtNumber = mEtNumber;}public VCInputType getmEtInputType() {return mEtInputType;}public void setmEtInputType(VCInputType mEtInputType) {this.mEtInputType = mEtInputType;}public int getmEtWidth() {return mEtWidth;}public void setmEtWidth(int mEtWidth) {this.mEtWidth = mEtWidth;}public int getmEtHeight() {return mEtHeight;}public void setmEtHeight(int mEtHeight) {this.mEtHeight = mEtHeight;}public int getmEtTextColor() {return mEtTextColor;}public void setmEtTextColor(int mEtTextColor) {this.mEtTextColor = mEtTextColor;}public float getmEtTextSize() {return mEtTextSize;}public void setmEtTextSize(float mEtTextSize) {this.mEtTextSize = mEtTextSize;}public int getmEtTextBg() {return mEtTextBg;}public void setmEtTextBg(int mEtTextBg) {this.mEtTextBg = mEtTextBg;}public int getmCursorDrawable() {return mCursorDrawable;}public void setmCursorDrawable(int mCursorDrawable) {this.mCursorDrawable = mCursorDrawable;}public enum VCInputType {NUMBER,NUMBERPASSWORD,TEXT,TEXTPASSWORD,}public VerificationCodeView(Context context, AttributeSet attrs) {super(context, attrs);this.mContext = context;@SuppressLint({"Recycle", "CustomViewStyleable"})TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.vericationCodeView);mEtNumber = typedArray.getInteger(R.styleable.vericationCodeView_vcv_et_number, 4);int inputType = typedArray.getInt(R.styleable.vericationCodeView_vcv_et_inputType, VCInputType.NUMBER.ordinal());mEtInputType = VCInputType.values()[inputType];mEtWidth = typedArray.getDimensionPixelSize(R.styleable.vericationCodeView_vcv_et_width, 120);mEtHeight = typedArray.getDimensionPixelSize(R.styleable.vericationCodeView_vcv_et_height, 120);mEtTextColor = typedArray.getColor(R.styleable.vericationCodeView_vcv_et_text_color, Color.BLACK);mEtTextSize = typedArray.getDimensionPixelSize(R.styleable.vericationCodeView_vcv_et_text_size, 16);mEtTextBg = typedArray.getResourceId(R.styleable.vericationCodeView_vcv_et_bg, R.drawable.bg_et_input_veri_code);mCursorDrawable = typedArray.getResourceId(R.styleable.vericationCodeView_vcv_et_cursor,R.drawable.bg_et_cursor);//释放资源typedArray.recycle();initView();}@SuppressLint("ResourceAsColor")private void initView() {for (int i = 0; i < mEtNumber; i++) {EditText editText = new EditText(mContext);initEditText(editText, i);addView(editText);if (i == 0) { //设置第一个editText获取焦点,并弹出软键盘editText.setFocusable(true);if(mContext instanceof Activity){((Activity)mContext).getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);}}}}private void initEditText(EditText editText, int i) {int childHPadding = 0;int childVPadding = 0;LayoutParams layoutParams = new LayoutParams(mEtWidth,mEtHeight);layoutParams.bottomMargin = childVPadding;layoutParams.topMargin = childVPadding;layoutParams.leftMargin = childHPadding;layoutParams.rightMargin = childHPadding;layoutParams.gravity = Gravity.CENTER;editText.setLayoutParams(layoutParams);editText.setGravity(Gravity.CENTER);editText.setId(i);editText.setCursorVisible(true);editText.setMaxEms(1);editText.setTextColor(mEtTextColor);editText.setTextSize(mEtTextSize);editText.setMaxLines(1);editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1)});switch (mEtInputType) {case NUMBER:editText.setInputType(InputType.TYPE_CLASS_NUMBER);break;case NUMBERPASSWORD:editText.setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_PASSWORD);break;case TEXT:editText.setInputType(InputType.TYPE_CLASS_TEXT);break;case TEXTPASSWORD:editText.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_PASSWORD);break;default:editText.setInputType(InputType.TYPE_CLASS_NUMBER);}editText.setPadding(0, 0, 0, 0);editText.setOnKeyListener(this);if(mEtTextBg != 0) {editText.setBackgroundResource(mEtTextBg);}//修改光标的颜色(反射)try {if(mCursorDrawable != 0) {Field f = TextView.class.getDeclaredField("mCursorDrawableRes");f.setAccessible(true);f.set(editText, mCursorDrawable);}} catch (Exception ignored) {}editText.addTextChangedListener(this);editText.setOnFocusChangeListener(this);editText.setOnKeyListener(this);}@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic void afterTextChanged(Editable s) {if (s.length() != 0) {focus();}}@Overridepublic boolean onKey(View v, int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_DEL) {backFocus();}return false;}@Overridepublic void setEnabled(boolean enabled) {int childCount = getChildCount();for (int i = 0; i < childCount; i++) {View child = getChildAt(i);child.setEnabled(enabled);}}/*** 获取焦点*/private void focus() {int count = getChildCount();EditText editText;//利用for循环找出还最前面那个还没被输入字符的EditText,并把焦点移交给它。for (int i = 0; i < count; i++) {editText = (EditText) getChildAt(i);if (editText.getText().length() < 1) {editText.setCursorVisible(true);editText.requestFocus();return;} else {editText.setCursorVisible(false);}}//如果最后一个输入框有字符,则返回结果EditText lastEditText = (EditText) getChildAt(mEtNumber - 1);if (lastEditText.getText().length() > 0) {getResult();}}private void backFocus() {//博主手机不好,经常点一次却触发两次`onKey`事件,就设置了一个防止多点击,间隔100毫秒。long startTime = System.currentTimeMillis();EditText editText;//循环检测有字符的`editText`,把其置空,并获取焦点。for (int i = mEtNumber - 1; i >= 0; i--) {editText = (EditText) getChildAt(i);if (editText.getText().length() >= 1 && startTime - endTime > 100) {editText.setText("");editText.setCursorVisible(true);editText.requestFocus();endTime = startTime;return;}}}private void getResult() {StringBuffer stringBuffer = new StringBuffer();EditText editText;for (int i = 0; i < mEtNumber; i++) {editText = (EditText) getChildAt(i);stringBuffer.append(editText.getText());}if (onCodeFinishListener != null) {onCodeFinishListener.onComplete(stringBuffer.toString());}}@Overridepublic void onFocusChange(View v, boolean hasFocus) {if (hasFocus) {focus();}}public interface OnCodeFinishListener {void onComplete(String content);}
}
2.values-attrs.xml中的定义:
<!-- 自定义验证码输入框--><declare-styleable name="vericationCodeView"><!--输入框的数量--><attr name="vcv_et_number" format="integer" /><!--输入类型--><attr name="vcv_et_inputType"><enum name="number" value="0" /><enum name="numberPassword" value="1" /><enum name="text" value="2" /><enum name="textPassword" value="3" /></attr><!--输入框的宽度--><attr name="vcv_et_width" format="dimension|reference" /><!--输入框的高度--><attr name="vcv_et_height" format="dimension|reference" /><!--输入框文字颜色--><attr name="vcv_et_text_color" format="color|reference" /><!--输入框文字大小--><attr name="vcv_et_text_size" format="dimension|reference" /><!--输入框背景--><attr name="vcv_et_bg" format="reference" /><!--光标样式--><attr name="vcv_et_cursor" format="reference" /></declare-styleable>
3.使用:
xml:
<com.shushan.ui.VerificationCodeViewandroid:id="@+id/verification_code_view"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/rl_already_send_to_phone"android:layout_centerHorizontal="true"android:layout_marginTop="29dp"app:vcv_et_width = "60.5dp"app:vcv_et_height = "56.5dp" />
Java:
private VerificationCodeView mVeriCodeView;
mVeriCodeView = (VerificationCodeView) findViewById(R.id.verification_code_view);
mVeriCodeView.setOnCodeFinishListener(this);//验证码输入完毕的回调
可自定义哪些部分看attrs.xml。
使用过程中遇到问题给我留言,会尽快回复。
欢迎参观博主的其他博客。
最后推荐给一些想进大厂或者还没有拿到心仪offer的攻城狮们一本书,由大厂java面试官胡书敏编写,满满的干货,助你进到想去的公司。
博主上传资源下载链接:
环状百分比显示视图源码:
https://download.csdn.net/download/yonghuming_jesse/10677919
自制免费无广告小说阅读APP下载:
https://download.csdn.net/download/yonghuming_jesse/10390364
全屏播放视频不拉伸源码:
https://download.csdn.net/download/yonghuming_jesse/10646274
科大讯飞语音评测服务接入源码:
https://download.csdn.net/download/yonghuming_jesse/10616924
android饺子播放器使用源码:
https://download.csdn.net/download/yonghuming_jesse/10619119
视频播放前显示视频第一帧源码:
https://download.csdn.net/download/yonghuming_jesse/10646332