Android开发4个验证码或者密码框
有些验证码框是输入的,输入一个自动跳到下一个框的,输完全部提交,也可以一个个删除的
一、思路:
自定义EditText
二、效果图
三、关键代码如下:
// 联系:893151960
public class SplitEditText extends AppCompatEditText {
//密码显示模式:隐藏密码,显示圆形
public static final int CONTENT_SHOW_MODE_PASSWORD = 1;
//密码显示模式:显示密码
public static final int CONTENT_SHOW_MODE_TEXT = 2;
//输入框相连的样式
public static final int INPUT_BOX_STYLE_CONNECT = 1;
//单个的输入框样式
public static final int INPUT_BOX_STYLE_SINGLE = 2;
//下划线输入框样式
public static final int INPUT_BOX_STYLE_UNDERLINE = 3;
//画笔
private RectF mRectFConnect;
private RectF mRectFSingleBox;
private Paint mPaintDivisionLine;
private Paint mPaintContent;
private Paint mPaintBorder;
private Paint mPaintUnderline;
//边框大小
private Float mBorderSize;
//边框颜色
private int mBorderColor;
//圆角大小
private float mCornerSize;
//分割线大小
private float mDivisionLineSize;
//分割线颜色
private int mDivisionColor;
//圆形密码的半径大小
private float mCircleRadius;
//密码框长度
private int mContentNumber;
//密码显示模式
private int mContentShowMode;
//单框和下划线输入样式下,每个输入框的间距
private float mSpaceSize;
//输入框样式
private int mInputBoxStyle;
//字体大小
private float mTextSize;
//字体颜色
private int mTextColor;
//每个输入框是否是正方形标识
private boolean mInputBoxSquare;
private OnInputListener inputListener;
private Paint mPaintCursor;
private CursorRunnable cursorRunnable;
private int mCursorColor;//光标颜色
private float mCursorWidth;//光标宽度
private int mCursorHeight;//光标高度
private int mCursorDuration;//光标闪烁时长
private int mUnderlineFocusColor;//下划线输入样式下,输入框获取焦点时下划线颜色
private int mUnderlineNormalColor;//下划线输入样式下,下划线颜色
public SplitEditText(Context context) {
this(context, null);
}
//这里没有写成默认的EditText属性样式android.R.attr.editTextStyle,这样会存在EditText默认的样式
public SplitEditText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/*public SplitEditText(Context context, AttributeSet attrs) {
super(context, attrs, android.R.attr.editTextStyle);
initAttrs(context, attrs);
}*/
public SplitEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(context, attrs);
}
private void initAttrs(Context c, AttributeSet attrs) {
TypedArray array = c.obtainStyledAttributes(attrs, R.styleable.SplitEditText);
mBorderSize = array.getDimension(R.styleable.SplitEditText_borderSize, dp2px(1f));
mBorderColor = array.getColor(R.styleable.SplitEditText_borderColor, Color.BLACK);
mCornerSize = array.getDimension(R.styleable.SplitEditText_corner_size, 0f);
mDivisionLineSize = array.getDimension(R.styleable.SplitEditText_divisionLineSize, dp2px(1f));
mDivisionColor = array.getColor(R.styleable.SplitEditText_divisionLineColor, Color.BLACK);
mCircleRadius = array.getDimension(R.styleable.SplitEditText_circleRadius, dp2px(5f));
mContentNumber = array.getInt(R.styleable.SplitEditText_contentNumber, 6);
mContentShowMode = array.getInteger(R.styleable.SplitEditText_contentShowMode, CONTENT_SHOW_MODE_PASSWORD);
mInputBoxStyle = array.getInteger(R.styleable.SplitEditText_inputBoxStyle, INPUT_BOX_STYLE_CONNECT);
mSpaceSize = array.getDimension(R.styleable.SplitEditText_spaceSize, dp2px(10f));
mTextSize = array.getDimension(R.styleable.SplitEditText_android_textSize, sp2px(16f));
mTextColor = array.getColor(R.styleable.SplitEditText_android_textColor, Color.BLACK);
mInputBoxSquare = array.getBoolean(R.styleable.SplitEditText_inputBoxSquare, true);
mCursorColor = array.getColor(R.styleable.SplitEditText_cursorColor, ContextCompat.getColor(c,R.color.colorAccent));
mCursorDuration = array.getInt(R.styleable.SplitEditText_cursorDuration, 500);
mCursorWidth = array.getDimension(R.styleable.SplitEditText_cursorWidth, dp2px(2f));
mCursorHeight = (int) array.getDimension(R.styleable.SplitEditText_cursorHeight, 0);
mUnderlineNormalColor = array.getInt(R.styleable.SplitEditText_underlineNormalColor, Color.BLACK);
mUnderlineFocusColor = array.getInt(R.styleable.SplitEditText_underlineFocusColor, 0);
array.recycle();
init();
}
private void init() {
mPaintBorder = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintBorder.setStyle(Paint.Style.FILL_AND_STROKE);
mPaintBorder.setStrokeWidth(mBorderSize);
mPaintBorder.setColor(mBorderColor);
mPaintDivisionLine = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintDivisionLine.setStyle(Paint.Style.STROKE);
mPaintDivisionLine.setStrokeWidth(mDivisionLineSize);
mPaintDivisionLine.setColor(mDivisionColor);
mPaintContent = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintContent.setTextSize(mTextSize);
mPaintCursor = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintCursor.setStrokeWidth(mCursorWidth);
mPaintCursor.setColor(mCursorColor);
mPaintUnderline = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintUnderline.setStrokeWidth(mBorderSize);
mPaintUnderline.setColor(mUnderlineNormalColor);
//避免onDraw里面重复创建RectF对象,先初始化RectF对象,在绘制时调用set()方法
//单个输入框样式的RectF
mRectFSingleBox = new RectF();
//绘制Connect样式的矩形框
mRectFConnect = new RectF();
//设置单行输入
setSingleLine();
//若构造方法中没有写成android.R.attr.editTextStyle的属性,应该需要设置该属性,EditText默认是获取焦点的
setFocusableInTouchMode(true);
//取消默认的光标
//这里默认不设置该属性,不然长按粘贴有问题(一开始长按不能粘贴,输入内容就可以长按粘贴)
//setCursorVisible(false);
//设置透明光标,若是直接不显示光标的话,长按粘贴会没效果
/*try {
Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
f.setAccessible(true);
f.set(this, 0);
} catch (Exception e) {
e.printStackTrace();
}*/
//设置光标的TextSelectHandle
//这里判断版本,10.0以及以上直接通过方法调用,以下通过反射设置
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// setTextSelectHandle(android.R.color.transparent);
// } else {
// //通过反射改变光标TextSelectHandle的样式
// try {
// Field f = TextView.class.getDeclaredField("mTextSelectHandleRes");
// f.setAccessible(true);
// f.set(this, android.R.color.transparent);
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//设置InputFilter,设置输入的最大字符长度为设置的长度
setFilters(new InputFilter[]{new InputFilter.LengthFilter(mContentNumber)});
}
@Override
protected void onAttachedToWindow() {
// L.e("SplitEditText","onAttachedToWindow------->");
super.onAttachedToWindow();
if(hasFocus()){
startCursor();
}
}
private void startCursor(){
if(cursorRunnable==null){
cursorRunnable = new CursorRunnable();
}
postDelayed(cursorRunnable, mCursorDuration);
}
private void stopCursor(){
if(cursorRunnable!=null){
removeCallbacks(cursorRunnable);
}
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if(focused){
startCursor();
}else{
stopCursor();
}
invalidate();
}
@Override
protected void onDetachedFromWindow() {
// L.e("SplitEditText","onDetachedFromWindow------->");
stopCursor();
super.onDetachedFromWindow();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mInputBoxSquare) {
int width = MeasureSpec.getSize(widthMeasureSpec);
//计算view高度,使view高度和每个item的宽度相等,确保每个item是一个正方形
float itemWidth = getContentItemWidthOnMeasure(width);
switch (mInputBoxStyle) {
case INPUT_BOX_STYLE_UNDERLINE:
setMeasuredDimension(width, (int) (itemWidth + mBorderSize));
break;
case INPUT_BOX_STYLE_SINGLE:
case INPUT_BOX_STYLE_CONNECT:
default:
setMeasuredDimension(width, (int) (itemWidth + mBorderSize * 2));
break;
}
}
}
@Override
protected void onDraw(Canvas canvas) {
//绘制输入框
switch (mInputBoxStyle) {
case INPUT_BOX_STYLE_SINGLE:
drawSingleStyle(canvas);
break;
case INPUT_BOX_STYLE_UNDERLINE:
drawUnderlineStyle(canvas);
break;
case INPUT_BOX_STYLE_CONNECT:
default:
drawConnectStyle(canvas);
break;
}
//绘制输入框内容
drawContent(canvas);
//绘制光标
if(hasFocus()){
drawCursor(canvas);
}
}
四、项目demo源码结构图:
有问题或者有需要源码可私信我