美文网首页Android开发经验谈Android开发Android开发
Android-打造一个属于自己的支付密码输入框

Android-打造一个属于自己的支付密码输入框

作者: 皮卡丘520 | 来源:发表于2018-07-10 14:22 被阅读227次

    首先上张效果图看看

    device-2018-07-10-112505.gif

    [图片上传中...((JQE1LR~C6[W9_R810HC4PJ.png-650e6a-1531195051613-0)]


    ps.png

    看这样一张图 我们首先需要绘制这样一个View

    1. 绘制外围Rect
    2. 绘制分割线
    3. 绘制圆点密码
    

    大家看到边框、分割线、圆点密码的颜色、大小、都是通过自定义属性而获得。

    自定义属性

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="PasswordEditText">
            <!--密码个数-->
            <attr name="passwordNumber" format="integer"/>
            <!--密码原点的半径-->
            <attr name="passwordRadius" format="dimension"/>
            <!--密码原点的颜色-->
            <attr name="passwordColor" format="color"/>
            <!--分割线的颜色-->
            <attr name="divisionLineColor" format="color"/>
            <!--分割线的大小  指宽度-->
            <attr name="divisionLineSize" format="dimension"/>
            <!--背景边框的颜色-->
            <attr name="bgColor" format="color"/>
            <!--背景边框的大小-->
            <attr name="bgSize" format="dimension"/>
            <!--背景边框的圆角大小-->
            <attr name="bgCorner" format="dimension"/>
    
        </declare-styleable>
    </resources>
    

    自定义密码输入框的View

    public class PasswordEditText extends AppCompatEditText {
    // 画笔-->绘制背景框
    private Paint mRectPaint;
    // 画笔--> 绘制密码
    private Paint mPasswordPaint;
    // 一个密码所占的宽度
    private int mPasswordItemWidth;
    // 密码的个数默认为6位数
    private int mPasswordNumber = 6;
    // 背景边框颜色
    private int mBgColor = Color.parseColor("#d1d2d6");
    // 背景边框大小
    private int mBgSize = 1;
    // 背景边框圆角大小
    private int mBgCorner = 0;
    // 分割线的颜色
    private int mDivisionLineColor = mBgColor;
    // 分割线的大小
    private int mDivisionLineSize = 1;
    // 密码圆点的颜色
    private int mPasswordColor = Color.parseColor("#000000");
    // 密码圆点的半径大小
    private int mPasswordRadius = 4;
    //密码输入完毕需要一个接口回调出去
    private PasswordFullListener mPasswordFullListener;
    
    public PasswordEditText(Context context) {
        this(context, null);
    }
    
    public PasswordEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttributeSet(context, attrs);
        //不显示光标
        setCursorVisible(false);
        //不弹出系统软键盘
        setInputType(InputType.TYPE_NULL);
        setBackground(null);
        initPaint();
    }
    
    /**
     * 初始化属性
     */
    private void initAttributeSet(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PasswordEditText);
        // 获取大小
        mDivisionLineSize = ( int ) array.getDimension(R.styleable.PasswordEditText_divisionLineSize, dip2px(mDivisionLineSize));
        mPasswordRadius = ( int ) array.getDimension(R.styleable.PasswordEditText_passwordRadius, dip2px(mPasswordRadius));
        mBgSize = ( int ) array.getDimension(R.styleable.PasswordEditText_bgSize, dip2px(mBgSize));
        mBgCorner = ( int ) array.getDimension(R.styleable.PasswordEditText_bgCorner, 0);
        // 获取颜色
        mBgColor = array.getColor(R.styleable.PasswordEditText_bgColor, mBgColor);
        mDivisionLineColor = array.getColor(R.styleable.PasswordEditText_divisionLineColor, mDivisionLineColor);
        mPasswordColor = array.getColor(R.styleable.PasswordEditText_passwordColor, mPasswordColor);
        array.recycle();
    }
    
    /**
     * 初始化画笔
     */
    private void initPaint() {
        //初始化绘制边框的画笔
        mRectPaint = new Paint();
        mRectPaint.setAntiAlias(true);
        mRectPaint.setDither(true);
        mRectPaint.setColor(mBgColor);
        //初始化密码远点的画笔
        mPasswordPaint = new Paint();
        mPasswordPaint.setAntiAlias(true);
        mPasswordPaint.setDither(true);
        mPasswordPaint.setColor(mPasswordColor);
    
    }
    
    
    @Override
    protected void onDraw(Canvas canvas) {
        //不需要调用super.onDraw(canvas); 为什么不需要呢?你去调用试试看,就明白为什么了
        //super.onDraw(canvas);
        //一个密码的宽度
        mPasswordItemWidth = (getWidth() - mBgSize * 2 - (mPasswordNumber - 1) * mDivisionLineSize) / mPasswordNumber;
        drawRect(canvas);
        drawDivisionLine(canvas);
        drawPassword(canvas);
        if (mPasswordFullListener != null) {
            //获取输入的密码
            String password = getText().toString().trim();
            if (password.length() == mPasswordNumber) {
                mPasswordFullListener.passwordFull(password);
            }
        }
    }
    
    /**
     * 绘制背景框
     *
     * @param canvas 画布
     */
    private void drawRect(Canvas canvas) {
        //矩形
        RectF rect = new RectF(mBgSize, mBgSize, getWidth() - mBgSize, getHeight() - mBgSize);
        mRectPaint.setStrokeWidth(mBgSize);
        //画空心
        mRectPaint.setStyle(Paint.Style.STROKE);
        if (mBgCorner == 0) {
            canvas.drawRect(rect, mRectPaint);
        } else {
            canvas.drawRoundRect(rect, mBgCorner, mBgCorner, mRectPaint);
        }
    }
    
    /**
     * 绘制分割线
     *
     * @param canvas 画布
     */
    private void drawDivisionLine(Canvas canvas) {
        mRectPaint.setStrokeWidth(mDivisionLineSize);
        for (int i = 0; i < mPasswordNumber - 1; i++) {
            int startX = mBgSize + (i + 1) * mPasswordItemWidth + i * mDivisionLineSize;
            int startY = 0;
            int endX = startX;
            int endY = getHeight() - mBgSize;
            canvas.drawLine(startX, startY, endX, endY, mRectPaint);
        }
    }
    
    /**
     * 绘制圆点密码
     *
     * @param canvas 画布
     */
    private void drawPassword(Canvas canvas) {
        //圆点密码是实行的
        mPasswordPaint.setStyle(Paint.Style.FILL);
        int length = getText().toString().length();
        for (int i = 0; i < length; i++) {
            int cx = mBgSize + i * mDivisionLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2;
            int cy = getHeight() / 2;
            canvas.drawCircle(cx, cy, mPasswordRadius, mPasswordPaint);
        }
    }
    
    public void addPassword(String number) {
        if (TextUtils.isEmpty(number)) {
            return;
        }
        //把密码取取出来
        String password = getText().toString().trim();
        if (password.length() <= mPasswordNumber) {
            //密码叠加
            password += number;
            setText(password);
        }
    }
    
    /**
     * 删除密码
     */
    public void deletePassword() {
        String password = getText().toString().trim();
        if (TextUtils.isEmpty(password)) {
            return;
        }
        password = password.substring(0, password.length() - 1);
        setText(password);
    }
    
    private int dip2px(int dip) {
        return ( int ) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dip, getResources().getDisplayMetrics());
    }
    
    /**
     * 设置一个密码输入完毕的监听器
     *
     * @param passwordFullListener Listener
     */
    public void setPasswordFullListener(PasswordFullListener passwordFullListener) {
        this.mPasswordFullListener = passwordFullListener;
    }
    
    public interface PasswordFullListener {
        void passwordFull(String password);
    }
    }
    

    最主要的是去求出每个密码的宽度、分割线的坐标位置(float startX, float startY, float stopX, float stopY)和原点密码的(cx,cy);

    key.png

    在看这样一个数字键盘,是写一个这样的布局,很简单的。关键是怎么给每一个View设置一个点击事件。每一个View 我们都去绑定一个Id,然后设置onClick事件吗?这样做,那是不可能的。具体这样做,看代码

     /**
     * 给每一个自定义数字键盘上的View 设置点击事件
     *
     * @param view
     */
    private void setItemClickListener(View view) {
        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = ( ViewGroup ) view;
            int childCount = viewGroup.getChildCount();
            for (int i = 0; i < childCount; i++) {
                //不断的给里面所有的View设置setOnClickListener
                View childView = (( ViewGroup ) view).getChildAt(i);
                setItemClickListener(childView);
            }
        } else {
            view.setOnClickListener(this);
        }
    }
    

    说下思路,键盘的整体布局是个LineaLayout,每一行布局是一个LineaLayout,然后每个LineaLayout会有三个子TextView。我们去递归下,这样每次循环都去拿View,不是ViewGroup,那就是View。

    源码地址:https://github.com/StevenYan88/PayPasswordEditText

    有任何问题,可以加小编的微信


    mmqrcode1521688883691.png

    相关文章

      网友评论

        本文标题:Android-打造一个属于自己的支付密码输入框

        本文链接:https://www.haomeiwen.com/subject/vojfpftx.html