• 安卓 验证码输入框InputCode(同时支持密码输入)


    继承EditText实现自定义验证码边框InputCode

    1、可修改边框焦点颜色及文字颜色大小,同时还支持自定义图片。

    2、键盘密码可随机仅供参考。

    演示:

              



    InputCodeEditText.java 自定义控件
    package com.dzw.inputcode;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.text.Editable;
    import android.text.InputFilter;
    import android.text.TextWatcher;
    import android.util.AttributeSet;
    import android.util.TypedValue;
    import android.view.ActionMode;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.EditText;
    
    /**
     * 自定义文本输入框,增加清空按钮
     */
    public class InputCodeEditText extends EditText implements TextWatcher {
    
        private Paint paint;//绘制方框
        private Paint textPaint;//绘制字体
        private float bgCenterY;
        private OnCodeCompleteListener onCodeCompleteListener;
        /**
         * 输入框的宽高
         */
        private int tvWidthSize = dip2px(40);
        /**
         * 文本的长度
         */
        private int mTextLen = 6;
        /**
         * 是否为密码输入框
         */
        private boolean isPassWord = true;//是否为密码输入框
        /**
         * 验证码间隔
         */
        private int intervalSize = dip2px(0);
        /**
         * 文字大小
         */
        private int textSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics());
        /**
         * 圆角大小
         */
        private int radius = dip2px(0);
        /**
         * 文字颜色
         */
        private int mTextColor = Color.BLACK;
        /**
         * 边框颜色
         */
        private int mBorderColor = Color.GRAY;
    
        /**
         * 边框颜色
         */
        private int mFocusBorderColor = -1;
    
        /**
         * 边框样式
         * -1表示自定义图片
         */
        private int mStyle = 0;
    
        /**
         * 自定义密码图片选中
         */
        private int mSelect = R.mipmap.input_selelct;
    
        /**
         * 自定义密码图片未选中选中
         */
        private int mUnSelect = R.mipmap.input_unselect;
        /**
         * 设置paint宽度
         */
        private int mStrokeWidth;
    
    
        public InputCodeEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(attrs);
        }
    
        public InputCodeEditText(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init(attrs);
        }
    
    
        private void init(AttributeSet attrs) {
            TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.CodeEditText);
            intervalSize = typedArray.getDimensionPixelSize(R.styleable.CodeEditText_tvIntervalSize, intervalSize);
            radius = typedArray.getDimensionPixelSize(R.styleable.CodeEditText_radius, radius);
            textSize = typedArray.getDimensionPixelSize(R.styleable.CodeEditText_tvTextSize, textSize);
            tvWidthSize = typedArray.getDimensionPixelSize(R.styleable.CodeEditText_tvWidth, tvWidthSize);
            mTextLen = typedArray.getInt(R.styleable.CodeEditText_tvLen, mTextLen);
            isPassWord = typedArray.getBoolean(R.styleable.CodeEditText_tvIsPwd, isPassWord);
            mTextColor = typedArray.getColor(R.styleable.CodeEditText_tvTextColor, mTextColor);
            mBorderColor = typedArray.getColor(R.styleable.CodeEditText_tvBorderColor, mBorderColor);
            mFocusBorderColor = typedArray.getColor(R.styleable.CodeEditText_tvFocusBorderColor, mFocusBorderColor);
            mStyle = typedArray.getInt(R.styleable.CodeEditText_tvStyle, mStyle);
            mSelect = typedArray.getResourceId(R.styleable.CodeEditText_tvCustomSelectIcon, mSelect);
            mUnSelect = typedArray.getResourceId(R.styleable.CodeEditText_tvUnCustomSelectIcon, mUnSelect);
            mStrokeWidth = typedArray.getDimensionPixelOffset(R.styleable.CodeEditText_tvStrokeWidth, dip2px(1));
            typedArray.recycle();
            setBackgroundColor(Color.WHITE);
            // 增加文本监听器.
            paint = new Paint();
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(mStrokeWidth);
            paint.setColor(mBorderColor);
    
            // 增加文本监听器.
            textPaint = new Paint();
            textPaint.setColor(mTextColor);
            textPaint.setAntiAlias(true);
            textPaint.setTextSize(textSize);
            setCursorVisible(false);
            setTextSize(0);
            disableCopyAndPaste(this);
            setFilters(new InputFilter[]{new InputFilter.LengthFilter(mTextLen)});
            addTextChangedListener(this);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            float bgWidth;
            bgWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
            float bgHeight;
            if (heightMode == MeasureSpec.EXACTLY) {
                bgHeight = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
            } else {
                bgHeight = tvWidthSize + dip2px(2);
            }
            bgCenterY = bgHeight / 2;
            setMeasuredDimension((int) bgWidth, (int) bgHeight);
        }
    
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (mStyle == 0) {
                drawDefaultRect(mTextLen, canvas);
            } else if (mStyle == 1) {
                drawStatEndRadiusRect(mTextLen, canvas);
            } else if (mStyle == 2) {
                drawWeChatRect(mTextLen, canvas);
            } else if (mStyle == 3) {
                drawLineRect(mTextLen, canvas);
            } else if (mStyle == -1) {
                drawBitmap(mTextLen, canvas);
            }
            drawText(mTextLen, canvas);
        }
    
    
        /**
         * 绘制前后圆角输入框不支持焦点输入框
         */
        private void drawStatEndRadiusRect(int count, Canvas canvas) {
            if (radius == 0) {
                radius = dip2px(5);
            }
            intervalSize = 0;
            int left = (getWidth() - count * (tvWidthSize + intervalSize)) / 2;
            for (int i = 1; i < count - 1; i++) {
                RectF rectF = new RectF(left + (tvWidthSize + intervalSize) * i,
                        bgCenterY - tvWidthSize / 2, left + (tvWidthSize + intervalSize) * i + tvWidthSize, bgCenterY + tvWidthSize / 2);
                canvas.drawRoundRect(rectF, 0, 0, paint);
            }
            RectF rectF = new RectF(left, bgCenterY - tvWidthSize / 2, left + (tvWidthSize + intervalSize) * (count - 1) + tvWidthSize, bgCenterY + tvWidthSize / 2);
            canvas.drawRoundRect(rectF, radius, radius, paint);
        }
    
        /**
         * 绘制输入框
         */
        private void drawDefaultRect(int count, Canvas canvas) {
            int left = (getWidth() - count * (tvWidthSize + intervalSize)) / 2;
            for (int i = 0; i < count; i++) {
                setFocusColor(i);
                RectF rectF = new RectF(left + (tvWidthSize + intervalSize) * i,
                        bgCenterY - tvWidthSize / 2, left + (tvWidthSize + intervalSize) * i + tvWidthSize, bgCenterY + tvWidthSize / 2);
                canvas.drawRoundRect(rectF, radius, radius, paint);
            }
        }
    
    
        /**
         * 仿安卓最新支付输入框
         */
        private void drawWeChatRect(int count, Canvas canvas) {
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
            int left = (getWidth() - count * (tvWidthSize + intervalSize)) / 2;
            for (int i = 0; i < count; i++) {
                setFocusColor(i);
                RectF rectF = new RectF(left + (tvWidthSize + intervalSize) * i,
                        bgCenterY - tvWidthSize / 2, left + (tvWidthSize + intervalSize) * i + tvWidthSize, bgCenterY + tvWidthSize / 2);
                canvas.drawRoundRect(rectF, radius, radius, paint);
            }
        }
    
    
        /**
         * 绘制输入框
         */
        private void drawLineRect(int count, Canvas canvas) {
            if (intervalSize == 0) {
                intervalSize = dip2px(5);
            }
            paint.setStrokeWidth(dip2px(2));
            int left = (getWidth() - count * (tvWidthSize + intervalSize)) / 2;
            for (int i = 0; i < count; i++) {
                setFocusColor(i);
                canvas.drawLine(left + (tvWidthSize + intervalSize) * i, bgCenterY + tvWidthSize / 2, left + (tvWidthSize + intervalSize) * i + tvWidthSize, bgCenterY + tvWidthSize / 2, paint);
            }
        }
    
        /**
         * 绘制图片
         */
        private void drawBitmap(int count, Canvas canvas) {
            if (intervalSize == 0) {
                intervalSize = dip2px(5);
            }
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), mUnSelect);
            Bitmap focusBitmap = BitmapFactory.decodeResource(getResources(), mSelect);
            tvWidthSize = bitmap.getWidth();
            int left = (getWidth() - count * (tvWidthSize + intervalSize)) / 2;
            for (int i = 0; i < count; i++) {
                if (getText().length() > i) {
                    canvas.drawBitmap(focusBitmap, left + (tvWidthSize + intervalSize) * i + tvWidthSize / 2 - bitmap.getWidth() / 2, bgCenterY - bitmap.getHeight() / 2, new Paint(Paint.ANTI_ALIAS_FLAG));
                } else {
                    canvas.drawBitmap(bitmap, left + (tvWidthSize + intervalSize) * i + tvWidthSize / 2 - bitmap.getWidth() / 2, bgCenterY - bitmap.getHeight() / 2, new Paint(Paint.ANTI_ALIAS_FLAG));
                }
            }
            if (bitmap.isRecycled()) {
                bitmap.recycle();
            }
            if (focusBitmap.isRecycled()) {
                focusBitmap.recycle();
            }
        }
    
    
        /**
         * 绘制文字
         */
        private void drawText(int count, Canvas canvas) {
            if (mStyle == -1) {
                return;
            }
            int left = (getWidth() - count * (tvWidthSize + intervalSize)) / 2;
            for (int i = 0; i < length(); i++) {
                String text = getText().toString().substring(i, i + 1);
                if (isPassWord) {
                    text = "●";
                }
                float textWidth = textPaint.measureText(text);
                Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
                float y = bgCenterY + (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
                canvas.drawText(text, left + (tvWidthSize + intervalSize) * i + tvWidthSize / 2 - textWidth / 2, y, textPaint);
            }
        }
    
    
        /**
         * 设置焦点颜色
         */
        private void setFocusColor(int i) {
            if (getText().length() == i && mFocusBorderColor != -1) {
                paint.setColor(mFocusBorderColor);
            } else {
                paint.setColor(mBorderColor);
            }
        }
    
    
        /**
         * 添加密碼
         */
        public void addText(String text) {
            if (getText().length() < mTextLen) {
                setText(getText().toString() + text);
            }
        }
    
        /**
         * 每次删除一个
         */
        public void removeText() {
            if (getText().length() > 0) {
                setText(getText().toString().substring(0, getText().length() - 1));
            }
        }
    
    
        /**
         * 把密度转换为像素
         */
        private int dip2px(float px) {
            final float scale = getScreenDensity();
            return (int) (px * scale + 0.5);
        }
    
        /**
         * 得到设备的密度
         */
        private float getScreenDensity() {
            return getResources().getDisplayMetrics().density;
        }
    
        /**
         * 禁止输入框复制粘贴菜单
         */
        public void disableCopyAndPaste(final EditText editText) {
            try {
                if (editText == null) {
                    return;
                }
    
                editText.setOnLongClickListener(v -> true);
                editText.setLongClickable(false);
    
                editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
                    @Override
                    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                        return false;
                    }
    
                    @Override
                    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                        return false;
                    }
    
                    @Override
                    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                        return false;
                    }
    
                    @Override
                    public void onDestroyActionMode(ActionMode mode) {
    
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    
        }
    
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            invalidate();
        }
    
        @Override
        public void afterTextChanged(Editable s) {
            if (onCodeCompleteListener != null) {
                if (getText().length() == mTextLen) {
                    onCodeCompleteListener.inputCodeComplete(getText().toString());
                } else {
                    onCodeCompleteListener.inputCodeInput(getText().toString());
                }
            }
        }
    
    
        /**
         * 输入完成回调接口
         */
        public interface OnCodeCompleteListener {
            //完成输入
            void inputCodeComplete(String verificationCode);
    
            //未完成输入
            void inputCodeInput(String verificationCode);
        }
    
    
        public void setOnCodeCompleteListener(OnCodeCompleteListener onCodeCompleteListener) {
            this.onCodeCompleteListener = onCodeCompleteListener;
        }
    }
    
    
    
     

    attrs.xml属性

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="CodeEditText">
            <attr name="tvWidth" format="dimension" />
            <!--文字大小-->
            <attr name="tvTextSize" format="dimension" />
            <!--输入个数 默认6个-->
            <attr name="tvLen" format="integer" />
            <!--是否为密码输入框-->
            <attr name="tvIsPwd" format="boolean" />
            <!--间隔-->
            <attr name="tvIntervalSize" format="dimension" />
            <!--圆角-->
            <attr name="radius" format="dimension" />
            <!--文字颜色-->
            <attr name="tvTextColor" format="reference|color" />
            <!--边框颜色-->
            <attr name="tvBorderColor" format="reference|color" />
            <!--边框焦点颜色-->
            <attr name="tvFocusBorderColor" format="reference|color" />
            <!--自定义选中图片-->
            <attr name="tvCustomSelectIcon" format="reference" />
            <!--自定义未选中图片-->
            <attr name="tvUnCustomSelectIcon" format="reference" />
            <!--设置边框粗细-->
            <attr name="tvStrokeWidth" format="dimension" />
    
            <!--边框样式-->
            <attr name="tvStyle">
                <!--默认无间隔正方形边框(间隔可自己设置通过tvIntervalSize)-->
                <enum name="defaultStyle" value="0" />
                <!--前后圆角边框 此样式不支持焦点颜色设置-->
                <enum name="startEndRadiusStyle" value="1" />
                <!--模拟最新微信支付边框-->
                <enum name="weChatPayStyle" value="2" />
                <!--设置底部横线边框-->
                <enum name="lineStyle" value="3" />
                <!--自定义图片样式,如果需要设置tvCustomSelectIcon和tvUnCustomSelectIcon 必须选择该属性-->
                <enum name="customStyle" value="-1" />
            </attr>
        </declare-styleable>
    </resources>

    源码:https://github.com/zhangwei-wade/inputcodeview

       

  • 相关阅读:
    在opencv3中实现机器学习之:利用正态贝叶斯分类
    在opencv3中进行图片人脸检测
    在opencv3中利用SVM进行图像目标检测和分类
    在opencv3中实现机器学习之:利用svm(支持向量机)分类
    在matlab和opencv中分别实现稀疏表示
    opencv2学习:计算协方差矩阵
    用python简单处理图片(3):添加水印
    Google protocol buffer在windows下的编译
    GEOS库学习之五:与GDAL/OGR结合使用
    GEOS库学习之四:几何关系判断
  • 原文地址:https://www.cnblogs.com/blogzhangwei/p/14627119.html
Copyright © 2020-2023  润新知