Android 密码输入框、验证码输入框,完整版;

接上篇,优化了一下代码,添加一些属性;

      "space" //每个输入框之间的间距;
       "strokeWidth" //边框的高度;
       "checkedColor"  //已输入的颜色
       "defaultColor" //未输入的默认颜色
       "textLength"  //规定输入长度
       "backColor"   //输入框的背景颜色
       "textColor"   //字体颜色
        "circle"   //密文密码 ● 的大小;
        "round"   //输入框的圆角弧度
        "textSize"   //字体大小
        "isPwd"   //是否密文输入 默认true
        "waitInputColor"   //待输入线的颜色
       "isWaitInput"  //是否显示待输入线 默认false

如何使用:

public class MainActivity extends AppCompatActivity {

    private PwdEditText p;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        p = findViewById(R.id.p);
        p.setOnTextChangeListener(new PwdEditText.OnTextChangeListener() {
            @Override
            public void onTextChange(String pwd) {
                if (pwd.length() == p.getTextLength()){
                    //输入监听
                    Toast.makeText(MainActivity.this,pwd,Toast.LENGTH_SHORT).show();
                }
            }
        });
        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                p.clearText(); //清空输入内容
            }
        });
    }
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

   <c.c.b.pwdinputedittext.PwdEditText
       android:id="@+id/p"
       android:layout_centerInParent="true"
       android:layout_width="330dp"
       android:layout_height="wrap_content"
       />
   <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="清空"
       android:id="@+id/btn"
       android:layout_below="@id/p"
       android:layout_centerHorizontal="true"
       />

</RelativeLayout>

看代码,PwdEditText :

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.v7.widget.AppCompatEditText;
import android.text.InputType;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;

public class PwdEditText extends AppCompatEditText {

     private Paint sidePaint , backPaint , textPaint;
     private Context mC;
    private String mText;
    private List<RectF> rectFS;
    private int StrokeWidth,spzceX ,spzceY,textSize;
    private int checkedColor,defaultColor,backColor ,textColor ,waitInputColor;
    private int textLength;
    private int Circle,Round;
    private boolean isPwd , isWaitInput;

    public PwdEditText(Context context) {
        super(context);

        mC = context;
        setAttrs( null);
        init();
    }

    public PwdEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        mC = context;
        setAttrs( attrs);
        init();
    }

    public PwdEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mC = context;
        setAttrs( attrs);
        init();
    }

    private void setAttrs(AttributeSet attrs) {
         TypedArray t = mC.obtainStyledAttributes(attrs, R.styleable.PwdEditText);
         if (t != null) {
             textLength = t.getInt(R.styleable.PwdEditText_textLength,6);
             spzceX = t.getDimensionPixelSize(R.styleable.PwdEditText_space, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3,getResources().getDisplayMetrics()));
             spzceY = t.getDimensionPixelSize(R.styleable.PwdEditText_space, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3,getResources().getDisplayMetrics()));
            StrokeWidth = t.getDimensionPixelSize(R.styleable.PwdEditText_strokeWidth, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics()));
            Round = t.getDimensionPixelSize(R.styleable.PwdEditText_round, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3,getResources().getDisplayMetrics()));
            Circle = t.getDimensionPixelSize(R.styleable.PwdEditText_circle, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,7,getResources().getDisplayMetrics()));
             textSize = t.getDimensionPixelSize(R.styleable.PwdEditText_textSize, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getResources().getDisplayMetrics()));
            checkedColor = t.getColor(R.styleable.PwdEditText_checkedColor,0xff44ce61);
            defaultColor = t.getColor(R.styleable.PwdEditText_defaultColor,0xffd0d0d0);
            backColor = t.getColor(R.styleable.PwdEditText_backColor,0xfff1f1f1);
            textColor = t.getColor(R.styleable.PwdEditText_textColor,0xFF444444);
            waitInputColor = t.getColor(R.styleable.PwdEditText_waitInputColor,0xFF444444);
            isPwd = t.getBoolean(R.styleable.PwdEditText_isPwd,true);
            isWaitInput = t.getBoolean(R.styleable.PwdEditText_isWaitInput,false);
            t.recycle();
         }
    }

    private void init() {
        setTextColor(0X00ffffff); //把用户输入的内容设置为透明
        setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_NORMAL);
        sidePaint = new Paint();
        backPaint = new Paint();
        textPaint = new Paint();

        rectFS = new ArrayList<>();
        mText = "" ;

        this.setBackgroundDrawable(null);
        setLongClickable(false);
        setTextIsSelectable(false);
        setCursorVisible(false);

    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        if (mText == null) {return;}
        //如果字数不超过用户设置的总字数,就赋值给成员变量mText;
        // 如果字数大于用户设置的总字数,就只保留用户设置的几位数字,并把光标制动到最后,让用户可以删除;
        if (text.toString().length() <= textLength){
            mText = text.toString();
        }else{
            setText(mText);
            setSelection(getText().toString().length());  //光标制动到最后
            //调用setText(mText)之后键盘会还原,再次把键盘设置为数字键盘;
            setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_NORMAL);
        }
        if (OnTextChangeListener != null) OnTextChangeListener.onTextChange(mText);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        switch (heightMode){
            case MeasureSpec.EXACTLY:
                heightSize = MeasureSpec.getSize(heightMeasureSpec);
                break;
            case MeasureSpec.AT_MOST:
                heightSize = widthSize/textLength;
                break;
        }
        setMeasuredDimension(widthSize,heightSize);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //边框画笔
        sidePaint.setAntiAlias(true);//消除锯齿
        sidePaint.setStrokeWidth(StrokeWidth);//设置画笔的宽度
        sidePaint.setStyle(Paint.Style.STROKE);//设置绘制轮廓
        sidePaint.setColor(defaultColor);
        //背景色画笔
        backPaint.setStyle(Paint.Style.FILL);
        backPaint.setColor(backColor);
        //文字的画笔
        textPaint.setTextSize(textSize);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setColor(textColor);

        int Wide = Math.min(getMeasuredHeight(), getMeasuredWidth() / textLength);

        for (int i = 0; i < textLength; i++) {
            //区分已输入和未输入的边框颜色
            if (mText.length() >= i){
                sidePaint.setColor(checkedColor);
            }else {
                sidePaint.setColor(defaultColor);
            }

            //RectF的参数(left,  top,  right,  bottom); 画出每个矩形框并设置间距,间距其实是增加左边框距离,缩小上下右边框距离;
            RectF rect = new RectF(i * Wide + spzceX, spzceY,i * Wide + Wide - spzceX,Wide - spzceY); //四个值,分别代表4条线,距离起点位置的线
            canvas.drawRoundRect(rect,Round,Round,backPaint); //绘制背景色
            canvas.drawRoundRect(rect,Round,Round,sidePaint); //绘制边框;
            rectFS.add(rect);

            if (isWaitInput && i == mText.length()) {  //显示待输入的线
                Paint l = new Paint();
                l.setStrokeWidth(3);
                l.setStyle(Paint.Style.FILL);
                l.setColor(waitInputColor);
                canvas.drawLine(i * Wide + Wide / 2, Wide / 2 - Wide / 5, i * Wide + Wide / 2, Wide / 2 + Wide / 5, l);
            }
        }
        //画密码圆点
        for (int j = 0; j < mText.length(); j++) {
            if (isPwd) {
                canvas.drawCircle(rectFS.get(j).centerX(), rectFS.get(j).centerY(), Circle, textPaint);
            }else {
                canvas.drawText(mText.substring(j,j+1),rectFS.get(j).centerX()-(textSize - spzceX)/2, rectFS.get(j).centerY()+(textSize - spzceY)/2, textPaint);
//                Rect textRect = new Rect();
//                textPaint.getTextBounds(mText.substring(j, j + 1), 0, 1, textRect);
//                canvas.drawText(mText.substring(j, j + 1), rectFS.get(j).left + (rectFS.get(j).right - rectFS.get(j).left) / 2 - textRect.width() / 2,
//                        rectFS.get(j).top + ((rectFS.get(j).bottom - rectFS.get(j).top) / 2) + textRect.height() / 2, textPaint);
            }
        }
    }

    private int dp2px(float dpValue){
        float scale=mC.getResources().getDisplayMetrics().density;
        return (int)(dpValue*scale+0.5f);
    }

    /**
     * 输入监听
     */
    interface OnTextChangeListener{
        void onTextChange(String pwd);
    }
    private OnTextChangeListener OnTextChangeListener;
    public void setOnTextChangeListener(OnTextChangeListener OnTextChangeListener){
        this.OnTextChangeListener = OnTextChangeListener;
    }

    /**
     * 清空所有输入的内容
     */
    public void clearText(){
        setText("");
        setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_NORMAL);
    }
    /**
     * 设置密码框间距
     */
    public void setSpace(int space){
        spzceX = space;
        spzceY = space;
    }
    /**
     * 设置密码框个数
     */
    public void setTextLength(int textLength){
        this.textLength = textLength;
    }
    /**
     * 获得密码框个数
     */
    public int getTextLength(){
        return this.textLength;
    }
    /**
     * 设置已输入密码框颜色
     */
    public void setcheckedColorColor(int checkedColor){
        this.checkedColor = checkedColor;
    }
    /**
     * 设置未输入密码框颜色
     */
    public void setdefaultColorColor(int defaultColor){
        this.defaultColor = defaultColor;
    }
    /**
     * 设置密码框背景色
     */
    public void setBackColor(int backColor){
        this.backColor = backColor;
    }
    /**
     * 设置密码圆点的颜色
     */
    public void setPwdTextColor(int textColor){
        this.textColor = textColor;
    }
    /**
     * 设置密码框 边框的宽度
     */
    public void setStrokeWidth(int width){
        StrokeWidth = width;
    }

    /**
     * 密码的圆点大小
     */
    public void setCircle(int Circle){
        this.Circle = Circle;
    }
    /**
     * 密码边框的圆角大小
     */
    public void setRound(int Round){
        this.Round = Round;
    }

    public int getStrokeWidth() {
        return StrokeWidth;
    }

    public int getSpzceX() {
        return spzceX;
    }

    public int getSpzceY() {
        return spzceY;
    }

    public int getCheckedColor() {
        return checkedColor;
    }

    public int getDefaultColor() {
        return defaultColor;
    }

    public int getBackColor() {
        return backColor;
    }

    public int getTextColor() {
        return textColor;
    }

    public int getCircle() {
        return Circle;
    }

    public int getRound() {
        return Round;
    }
    public int gettextSize() {
        return textSize;
    }

    public void settextSize(int textSize) {
        this.textSize = textSize;
    }

    public boolean isPwd() {
        return isPwd;
    }

    /**
     * 是否密文输入
     * @param pwd
     */
    public void setPwd(boolean pwd) {
        isPwd = pwd;
    }

    public int getWaitInputColor() {
        return waitInputColor;
    }

    /**\
     * 待输入线的颜色
     * @param waitInputColor
     */
    public void setWaitInputColor(int waitInputColor) {
        this.waitInputColor = waitInputColor;
    }

    public boolean isWaitInput() {
        return isWaitInput;
    }

    /**
     * 是否显示待输入的线
     * @param waitInput
     */
    public void setWaitInput(boolean waitInput) {
        isWaitInput = waitInput;
    }

}

style中的代码:

    <declare-styleable name="PwdEditText">
        <attr name="space" format="dimension"/>
        <attr name="strokeWidth" format="dimension"/>
        <attr name="checkedColor" format="color"/>
        <attr name="defaultColor" format="color"/>
        <attr name="textLength" format="integer"/>
        <attr name="backColor" format="color"/>
        <attr name="textColor" format="color"/>
        <attr name="circle" format="dimension"/>
        <attr name="round" format="dimension"/>
        <attr name="textSize" format="dimension"/>
        <attr name="isPwd" format="boolean"/>
        <attr name="waitInputColor" format="color"/>
        <attr name="isWaitInput" format="boolean"/>
    </declare-styleable>

猜你喜欢

转载自blog.csdn.net/qq_35605213/article/details/82702474