Android自定义View--模仿支付宝支付密码框,自定义密码输入框

按照惯例先上效果图:
自定义密码输入框

⚠️分析:

一、需要调用输入数字输入框
二、对输入框的监控
三、画圆角的矩形
四、画分割线
五、画密码的原点

思路:

EditText符合前两个需求,但是我们不想显示输入内容与默认的密码样式。所以我们可以自定义View继承EdiText。来实现下面三种需求。
一、我们只需要EditText调用数字输入框和对文字的监控特性即可,其他的我们自定义

 android:inputType="number"

二、我们在onDraw方法里画一个圆角矩形画笔为填充模式覆盖住原有EdiText的显示效果,再画一个小一点圆角矩形在刚出的圆角矩形里面,来实现圆角矩形的边框。(其实有各种实现方式)
三、然后根据密码长度来画“密码长度-1”个分割线
四、重写监听文字变化来画密码的圆点。

代码如下:代码里有详细注释


public class PasswordInputView extends EditText {
    private String TAG = "PasswordInputView";
    private Context mContext;
    private int passwordSize = 6;//密码的个数这里是默认值,也可以通过自定义属性来设置其他数值
    private int borderWidth = 6;//密码输入框的边框宽度px
    private int borderRadius = 6;//密码输入框矩形圆角的半径
    private int borderColor = 0xff333333;//密码输入框边框的颜色
    private int passwordWidth = 12;//密码的宽度
    private int passwordColor = 0xff000000;//密码的颜色
    private int defaultSplitLineWidth = 3; //px

    private int allPasswordWidth;//控件的总宽度
    private int allPasswordHight;//控件的总高度

    private Paint mPaint;//边框画笔
    private Paint pwPaint;//密码画笔

    private int passwordTextSize;//输入密码的个数
    private String password;//密码

    private onPasswordChangedListener onPasswordChangedListener;

    public void setOnPasswordChangedListener(PasswordInputView.onPasswordChangedListener onPasswordChangedListener) {
        this.onPasswordChangedListener = onPasswordChangedListener;
    }


    //获取密码
    public String getPassword() {
        return password;
    }

    //注意 :只能复写这个构造函数,切只能在这里初始化,不然你会发现EditText的特性就没有来
    public PasswordInputView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }


    private void init(Context context, AttributeSet attrs) {
        mContext = context;
        /**
         * 初始化各种自定义属性
         * */
        TypedArray typedArray = mContext.obtainStyledAttributes(attrs,R.styleable.PasswordInputView);
        passwordSize = typedArray.getInt(R.styleable.PasswordInputView_passwordLength, passwordSize);
        borderWidth = typedArray.getDimensionPixelSize(R.styleable.PasswordInputView_borderWidth, borderWidth);
        borderRadius = typedArray.getDimensionPixelSize(R.styleable.PasswordInputView_borderRadius, borderRadius);
        borderColor = typedArray.getColor(R.styleable.PasswordInputView_borderColor, borderColor);
        passwordWidth = typedArray.getDimensionPixelSize(R.styleable.PasswordInputView_passwordWidth, passwordWidth);
        passwordColor = typedArray.getColor(R.styleable.PasswordInputView_passwordColor, passwordColor);
        Log.d(TAG,"borderRadius:"+borderRadius);
        Log.d(TAG,"passwordSize:"+passwordSize);
        typedArray.recycle();

        //初始化边框画笔
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(borderWidth);

        //初始化密码画笔
        pwPaint = new Paint();
        pwPaint.setAntiAlias(true);
        pwPaint.setStyle(Paint.Style.FILL);
        pwPaint.setColor(passwordColor);
        pwPaint.setStrokeWidth(passwordWidth);

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        Log.d(TAG, "onSizeChanged");
        allPasswordWidth = w;
        allPasswordHight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d(TAG, "onDraw");


        Log.d(TAG, "allPasswordWidth:" + allPasswordWidth);
        Log.d(TAG, "borderRadius:" + borderRadius);
        //画一个矩形遮住显示的文字
        mPaint.setColor(borderColor);
        canvas.drawRoundRect(0, 0, allPasswordWidth, allPasswordHight, borderRadius, borderRadius, mPaint);
        //再画一个白色矩形这种上面的矩形内部,形成假的边框
        mPaint.setColor(Color.WHITE);
        canvas.drawRoundRect(defaultSplitLineWidth, defaultSplitLineWidth,
                allPasswordWidth - defaultSplitLineWidth, allPasswordHight - defaultSplitLineWidth,borderRadius,borderRadius, mPaint);

        //画分割线
        int lineStartAndEndx = allPasswordWidth / passwordSize;
        int lineStarty = 0;
        int lineendy = allPasswordHight;
        mPaint.setColor(borderColor);
        mPaint.setStrokeWidth(defaultSplitLineWidth);
        for (int i = 1; i < passwordSize; i++) {
            canvas.drawLine(lineStartAndEndx, lineStarty, lineStartAndEndx, lineendy, mPaint);
            lineStartAndEndx += allPasswordWidth / passwordSize;
        }

        //画密码圆
        int circleX = allPasswordWidth / passwordSize / 2;
        int circleY = allPasswordHight / 2;
        if (passwordTextSize > 0) {
            for (int i = 0; i < passwordTextSize; i++) {
                canvas.drawCircle(circleX, circleY, passwordWidth, pwPaint);
                circleX += allPasswordWidth / passwordSize;
            }

        }
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        //监听文字变化大于密码设定长度不记录
        Log.d(TAG,"onTextChanged:"+passwordSize);
        if (text.length() <= passwordSize){
            passwordTextSize = text.length();
            password = text.toString();
            if (onPasswordChangedListener != null)
                onPasswordChangedListener.setPasswordChanged();
        }else {
            text = password;
        }
        invalidate();

    }

    //设置监听密码变化
    public interface onPasswordChangedListener {
        public void setPasswordChanged();
    }
}

自定义属性文件attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="PasswordInputView">
        <attr name="passwordLength" format="integer"/>
        <attr name="borderWidth" format="dimension"/>
        <attr name="borderRadius" format="dimension"/>
        <attr name="borderColor" format="color"/>
        <attr name="passwordWidth" format="dimension"/>
        <attr name="passwordColor" format="color"/>
    </declare-styleable>
</resources>

布局中的使用

android:maxLength=“6” 密码的限制长度
app:passwordLength=“6” 密码的中长度
这两个要设置一样,这点其实可以再优化,设置一个值即可。

<com.goodboy.mile.View.PasswordInputView
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:id="@+id/password_view"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@null"
        android:cursorVisible="false"
        android:inputType="number"
        android:maxLength="6"
        app:passwordLength="6"
        app:borderWidth="10dp"
        app:borderRadius="8dp"
        app:passwordWidth="6dp"
        app:passwordColor="#ffaaaaaa"/>

猜你喜欢

转载自blog.csdn.net/yanwenyuan0304/article/details/95060901