仿淘宝支付密码输入框

相信大家对支付保的密码输入框应该很熟悉吧(毕竟经常用),先给大家看一下支付宝的

支付保界面

好吧回归正题,昨天我的部门老大给了我一个APP让我看看里面有那些好的地方,可以放到我们自己APP中的模块、功能、流程(哎,小公司就这样各种抄袭),在这个APP中我看到了这个密码输入框我就想自己写一个,而身为菜鸟的我没有什么好的思路,就去github的海洋中游了一圈down了几个开源项目找了找思路,最终有了这个。

设计思路:

实现这种输入的效果我们得用自定义View
第一步:创建一个类继承EditText(我继承的是AppCompatEditText,其实是一样的)
第二步:创建一个attr文件,在里面写好自己的自定义属性。
第三步:重写onDraw方法画界面
第四步:写一个回调接口将密码输入完成的操作回调出去。

设计思路大概就是这样的,其中最重要的就是在onDraw方法中画界面,其他的都非常的简单,这里也主要将onDraw方法中的操作,其他步骤一会看完整的代码(我会在文章的最后吧代码贴出来)

界面的绘制
界面的绘制我的思路是这样的:
第一步:绘制背景,背景为浅灰色背景
第二步:绘制白色的内容区,内容区比背景稍微窄一点、矮一点,这样就能形成咱这个输入框的外边框啦。
第三步:绘制分割线
第四步:绘制输入的内容(用小圆点代替)

背景的绘制,代码如下:

  //画背景
        RectF bgRect = new RectF(0, 0, width, height);
        //设置背景的颜色
        bgPaint.setColor(borderColor);
        canvas.drawRect(bgRect, bgPaint);

内容区的绘制,代码如下:

  //画内容区
        RectF contentRect = new RectF(bgRect.left + borderWidth, bgRect.top + borderWidth, bgRect.right - borderWidth, bgRect.bottom - borderWidth);
        rectPaint.setColor(chunkColor);
        canvas.drawRect(contentRect, rectPaint);

上述代码中borderWidth这个值,你可以把它认为是外边框的宽度,我的这个外边框的形成其实就是一个大矩形里面套了一个小矩形,这两个矩形的颜色不一样而形成的外边框。

绘制分割线,代码如下:

        //画分割线
        bgPaint.setStrokeWidth(linesWidth);//设置分割线的宽度
        bgPaint.setColor(linesColor);//设置分割线的颜色
        for (int i = 0; i < defultCount; i++) {
            float x = width / defultCount * i;
            canvas.drawLine(x, borderWidth, x, height - borderWidth, bgPaint);
        }

上述代码中最重要的就是这句: float x = width / defultCount * i;
这句话的意思就是计算分割线的位置,分割线y轴是不变的改变的就是x轴的值,我们来解释一下这段代码;
width:控件的整体长度
defultCount:控件有几个格子
i:i是从0开始的,它在for循环中递增从而算出第一个分割线到最后一个分割线x轴的位置

绘制密码,代码如下:

    if (textLength > 0) {
            //画密码
            int j = getWidth() / defultCount / 2;
            for (int i = 0; i < textLength; i++) {
                int cx = width / defultCount * i + j;
                circleRadius = height / 6;
                canvas.drawCircle(cx, getHeight() / 2, circleRadius, bgPaint);
            }
        }

我们在输入的密码长度大于零的时候才开始绘制

上面的代码我就不做解释了(伙伴们应该看的懂吧),到这里我们的绘制工作就算是完结了,下面就是对输入内容的监听并回调。

对输入内容的监听:

为了监听输入内容,我们得重写onTextChanged方法,代码如下:

  @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        textLength = text.toString().length();
        invalidate();
        if (textLength == defultCount) {
            if (onInputFinishListener != null) {
                onInputFinishListener.inputFinish(text.toString());
            }
        }
    }

这里面需要我们自己去写一个回调接口,如下:

//声明接口
  private OnInputFinishListener onInputFinishListener;

//接口的set方法
    public void setOnInputFinishListener(OnInputFinishListener onInputFinishListener) {
        this.onInputFinishListener = onInputFinishListener;
    }
//接口的本体
    public interface OnInputFinishListener {
        void inputFinish(String text);
    }

—————————————————————我是分割线——————————————————

要是大家没兴趣看文章的话可以直接copy代码,代码如下:

package com.example.administrator.coo.passwordEditText;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import android.view.ViewGroup;

import com.example.administrator.coo.R;

/**
 * Created by zhanglei on 2017/6/9.
 * 仿支付保密码输入框
 */

public class PasswordEditText extends AppCompatEditText {


    /**
     * 输入格子的数量
     */
    private int defultCount = 6;

    /**
     * 用来画背景的画笔
     */
    private Paint bgPaint = new Paint();

    /**
     * 用来画内容块的画笔
     */
    private Paint rectPaint = new Paint();

    /**
     * 密码的长度
     */
    private int textLength = 0;

    /**
     * 分割线的宽度
     */
    private float linesWidth = 0;

    /**
     * 边框的宽度
     */
    private float borderWidth = 0;

    /**
     * 边框的颜色
     */
    private int borderColor = 0xFFCCCCCC;

    /**
     * 分割线的颜色
     */
    private int linesColor = 0xFFCCCCCC;

    /**
     * 密码圆点的半径
     */
    private int circleRadius;

    /**
     * 内容块底色
     */
    private int chunkColor = Color.WHITE;

    public PasswordEditText(Context context) {
        super(context);
    }

    public PasswordEditText(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PasswordEditText, 0, 0);
        defultCount = a.getInteger(R.styleable.PasswordEditText_pe_count, defultCount);
        borderWidth = a.getDimension(R.styleable.PasswordEditText_pe_lineWidth, linesWidth);
        linesWidth = a.getDimension(R.styleable.PasswordEditText_pe_cuttingLineWidth, borderWidth);
        borderColor = a.getColor(R.styleable.PasswordEditText_pe_lineColor, this.borderColor);
        linesColor = a.getColor(R.styleable.PasswordEditText_pe_cuttingLineColor, linesColor);
        chunkColor = a.getColor(R.styleable.PasswordEditText_pe_chunkColor, chunkColor);
        a.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //获取控件的宽
        int width = getWidth();
        //获取控件的高
        int height = getHeight();
        //分割线的宽度
        linesWidth = getLinesWidth() - 3;
        //边线的宽度
        borderWidth = getLinesWidth() - 1;
        /* 大家可以看到我获取分割线的宽度和边线的宽度的代码是写在onDraw方法里的,这样做会使在布局中设置的宽度不起作用,但是如果不这么写的话我不知道要给一个多宽的默认值,所以就只能先这样了,大家如果有好的方法和思路记得给我说呀,谢谢。 */
        //画背景
        RectF bgRect = new RectF(0, 0, width, height);
        //设置背景的颜色
        bgPaint.setColor(borderColor);
        canvas.drawRect(bgRect, bgPaint);

        //画内容区
        RectF contentRect = new RectF(bgRect.left + borderWidth, bgRect.top + borderWidth, bgRect.right - borderWidth, bgRect.bottom - borderWidth);
        rectPaint.setColor(chunkColor);
        canvas.drawRect(contentRect, rectPaint);

        //画分割线
        bgPaint.setStrokeWidth(linesWidth);
        bgPaint.setColor(linesColor);
        for (int i = 0; i < defultCount; i++) {
            float x = width / defultCount * i;
            canvas.drawLine(x, borderWidth, x, height - borderWidth, bgPaint);
        }

        if (textLength > 0) {
            //画密码
            int j = getWidth() / defultCount / 2;
            for (int i = 0; i < textLength; i++) {
                int cx = width / defultCount * i + j;
                circleRadius = height / 6;
                canvas.drawCircle(cx, getHeight() / 2, circleRadius, bgPaint);
            }
        }
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        textLength = text.toString().length();
        invalidate();
        if (textLength == defultCount) {
            if (onInputFinishListener != null) {
                onInputFinishListener.inputFinish(text.toString());
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private float getLinesWidth() {
        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
        //获取控件左边的margin值
        int leftMargin = lp.leftMargin;
        //获取控件右边的margin值
        int rightMargin = lp.rightMargin;
        //边框及分割线的宽度
        return (leftMargin + rightMargin + getWidth()) / 200;
    }

    private OnInputFinishListener onInputFinishListener;

    public void setOnInputFinishListener(OnInputFinishListener onInputFinishListener) {
        this.onInputFinishListener = onInputFinishListener;
    }

    public interface OnInputFinishListener {
        void inputFinish(String text);
    }
}

这里还有一个需要你copy的,这个是自定以的一些属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="PasswordEditText">
        <attr name="pe_count" format="integer" />
        <attr name="pe_lineWidth" format="dimension" />
        <attr name="pe_cuttingLineWidth" format="dimension" />
        <attr name="pe_lineColor" format="color" />
        <attr name="pe_cuttingLineColor" format="color" />
        <attr name="pe_passwordColor" format="color" />
        <attr name="pe_chunkColor" format="color" />
    </declare-styleable>

</resources>

文章的最后给大家看一下,这个密码输入框的效果图
支付保界面

当输入完成时会回调OnInputFinishListener 接口中的inputFinish方法获取输入的内容。

文章到此结束,希望能给大家带来帮助

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值