Android开发4个验证码或者密码框

209 阅读3分钟
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源码结构图:

在这里插入图片描述有问题或者有需要源码可私信我