自定義View-驗證碼輸入框

驗證碼輸入框

1.先看下樣式

在這裏插入圖片描述
2.直接上代碼

public class MyVcode extends AppCompatEditText {
    private int mFigures = 0;// 驗證碼個數
    private int mCodeMargin = 0;// 驗證碼之間的間距
    private int mSelectColor = 0;// 選中框的顏色
    private int mNormalColor = 0;// 普通框的顏色
    private float mBorderWidth = 0f;// 邊框的厚度

    Paint mNormalPaint = new Paint();
    Paint mSelectPaint = new Paint();
    Paint mOkContentPain = new Paint();//填寫了內容的驗證碼

    private OnVerifyCodeChangedListener onVerifyCodeChangedListener;
    private int mCurrentPosition = 0;// 當前驗證碼的位置
    private int mEachRectLength = 0;// 矩形邊長
    public MyVcode(Context context) {
        super(context, null);
    }



    public MyVcode(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttr(context,attrs);
        initPaint();
        setFocusableInTouchMode(true);
        initTextChangeListerner();
    }

    private void initTextChangeListerner() {
        addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                mCurrentPosition = getText().length();
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                mCurrentPosition = getText().length();
                postInvalidate();
                if (onVerifyCodeChangedListener!=null){
                    onVerifyCodeChangedListener.onVerCodeChanged(getText().toString(),start,before,count);
                }
            }

            @Override
            public void afterTextChanged(Editable s) {
                mCurrentPosition = getText().length();
                postInvalidate();
                if (getText().length() == mFigures){
                    if (onVerifyCodeChangedListener!=null){
                        onVerifyCodeChangedListener.onInputCompleted(getText().toString());
                    }
                }else if (getText().length()>mFigures){
                    getText().delete(mFigures,getText().length());
                }
            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction()==MotionEvent.ACTION_DOWN){
            requestFocus();
            setSelection(getText().length());
            showKeyBoard(getContext());
            return false;
        }

        return super.onTouchEvent(event);

    }

    private void showKeyBoard( Context context) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(this, InputMethodManager.SHOW_FORCED);
    }

    private void initAttr(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.VerifyCodeEditText);
        mFigures = ta.getInteger(R.styleable.VerifyCodeEditText_figures, 6);
        mCodeMargin = (int) ta.getDimension(R.styleable.VerifyCodeEditText_codeMargin, 0f);
        mSelectColor = ta.getColor(R.styleable.VerifyCodeEditText_selectBorderColor,getResources().getColor(R.color.base_barcolor));
        mNormalColor =
                ta.getColor(
                        R.styleable.VerifyCodeEditText_normalBorderColor,
                        getResources().getColor(android.R.color.darker_gray)
                );
        mBorderWidth = ta.getDimension(R.styleable.VerifyCodeEditText_borderWidth, 1f);

      /*  mCursorColor =
                ta.getColor(
                        R.styleable.VerifyCodeEditText_cursorColor,
                        getResources().getColor(android.R.color.darker_gray)
                );
        ta.recycle();*/

      /*  // force LTR because of bug: https://github.com/JustKiddingBaby/VercodeEditText/issues/4
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            layoutDirection = LAYOUT_DIRECTION_LTR
        }*/
    }

    private void initPaint() {
        mNormalPaint.setAntiAlias(true);
        mNormalPaint.setColor(mNormalColor);
        mNormalPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mNormalPaint.setStrokeWidth(mBorderWidth);

        mSelectPaint.setAntiAlias(true);
        mSelectPaint.setColor(mSelectColor);
        mSelectPaint.setStyle(Paint.Style.STROKE);
        mSelectPaint.setStrokeWidth(mBorderWidth);


        mOkContentPain.setAntiAlias(true);
        mOkContentPain.setColor(mSelectColor);
        mOkContentPain.setStyle(Paint.Style.FILL_AND_STROKE);
        mOkContentPain.setStrokeWidth(mBorderWidth);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        // 每個矩形的寬度  相當於我門圓的直徑
        mEachRectLength = size ;

    }

    @Override
    protected void onDraw(Canvas canvas) {
        //super.onDraw(canvas);
        Editable text = this.getText();
        mCurrentPosition = text.length();
        int width = mEachRectLength -getPaddingLeft() - getPaddingRight();

        for (int i =0 ;i< mFigures;i++){
            canvas.save();
            float  start = width*i +mCodeMargin*i+mBorderWidth;
            float end = start+width - mBorderWidth;
            if (i==mFigures-1){
                end -= mBorderWidth;
            }
            RectF rect = new RectF(start, mBorderWidth, end, width - mBorderWidth);
            //畫底色
            canvas.drawArc(rect, 0f, 360f, true, mNormalPaint);
            if (i == mCurrentPosition) {//選中的下一個狀態
                canvas.drawArc(rect, 0f, 360f, true, mNormalPaint);
                canvas.drawArc(rect, 0f, 360f, true, mSelectPaint);
            }else {
                canvas.drawArc(rect, 0f, 360f, true, mNormalPaint);
            }

            if (mCurrentPosition>i){
                //畫已經有內容的
                canvas.drawArc(rect, 0f, 360f, true, mOkContentPain);
            }
            canvas.restore();

        }
        String s = text.toString();

        //畫文字
        for (int i = 0;i<mCurrentPosition;i++){
            canvas.save();
            int start = width * i + mCodeMargin * i;
            float x = start + width / 2f;
            TextPaint paint = getPaint();
            paint.setTextAlign(Paint.Align.CENTER);
            paint.setColor(getCurrentTextColor());
            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
            float baseline = (width - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
            canvas.drawText(s.substring(i,i+1), x, baseline, paint);
            canvas.restore();
        }



    }

    /**
     * 驗證碼變化時候的監聽事件
     */
    interface OnVerifyCodeChangedListener {
        /**
         * 當驗證碼變化的時候
         */
        public void onVerCodeChanged(String s,int start,  int before, int count);

        /**
         * 輸入完畢後的回調
         */
        public void onInputCompleted(String s);
    }


}

3.自定義的屬性

   <!--驗證碼的屬性-->
    <declare-styleable name="VerifyCodeEditText">
        <attr name="figures" format="integer"/><!--驗證碼的個數-->
        <attr name="codeMargin" format="dimension"/><!--驗證碼的之間的間隔-->
        <attr name="selectBorderColor" format="color|reference"/><!--選中的邊框顏色-->
        <attr name="normalBorderColor" format="color|reference"/><!--普通的邊框顏色-->
        <attr name="borderWidth" format="dimension"/><!--邊框的厚度 -->
        <attr name="cursorColor" format="color|reference"/><!--已經有內容的顏色 -->
    </declare-styleable>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章