Android实现自定义PasswordInputView密码输入

欢迎来到“实现自定义密码输入控件”这一章节,PasswordInputView定义了密码输入的监听,支持直接在布局文件定义属性值、支持直接获取密码输入的长度、原始密码……

先上图

自定义密码输入框控件
自定义密码输入框控件

PasswordInputView是做什么的?

PasswordInputView是一个自定义密码输入的控件,类似支付宝、微信支付的密码输入,同时定义了密码输入的监听,支持直接在布局文件定义属性值、支持直接获取密码输入的长度、原始密码等,还可以扩展其他方法,请自行实现。

实现原理

1.创建一个类 ‘PasswordInputView’ ,让其继承EditText,因为我们要实现的自定义view是用来密码输入的,所以必须继承EditText。

2.为了在布局(layout)文件(.xml)能直接定义PasswordInputView各个属性的值,我们需要定义PasswordInputView带AttributeSet 参数的构造方法。

public PasswordInputView(Context context, AttributeSet attr) {
    super(context, attr);
    init(context, attr);
}

3.在’value/attrs.xml’中定义PasswordInputView各个属性及其类型,如:

<?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>

4.重载OnDraw(Canvas canvas)方法,并在其实现画边框、画内容区域(以填充模式绘制Paint.Style.FILL)、画分割线、画实心圆点(密码)。有人可能会问:画了边框、分割线,就可以了,为什么还要画内容区域?问得好,笔者在实现过程中也碰到这个问题,当时没有画内容区域,导致输入的原始内容也显示出来了(如下异常图),所以画内容区域(以填充模式绘制Paint.Style.FILL)是为了掩盖原始内容不被发现,切记必不可少
异常图

正确代码如下:

    private void init(Context context, AttributeSet attr) {
        TypedArray ta = context.obtainStyledAttributes(attr, R.styleable.Passwordinputview);
        try {
            passwordLength = ta.getInt(R.styleable.Passwordinputview_passwordLength, passwordLength);
            borderWidth = ta.getDimensionPixelSize(R.styleable.Passwordinputview_borderWidth, borderWidth);
            borderRadius = ta.getDimensionPixelSize(R.styleable.Passwordinputview_borderRadius, borderRadius);
            borderColor = ta.getColor(R.styleable.Passwordinputview_borderColor, borderColor);
            passwordWidth = ta.getDimensionPixelSize(R.styleable.Passwordinputview_passwordWidth, passwordWidth);
            passwordColor = ta.getColor(R.styleable.Passwordinputview_passwordColor, passwordColor);
        } catch (Exception e) {

        }
        ta.recycle();

        borderPaint = new Paint();
        borderPaint.setAntiAlias(true);
        borderPaint.setColor(borderColor);
        borderPaint.setStrokeWidth(borderWidth);
        borderPaint.setStyle(Paint.Style.FILL); //以填充模式来画,防止原始输入内容显示出来

        passwordPaint = new Paint();
        passwordPaint.setAntiAlias(true);
        passwordPaint.setColor(passwordColor);
        passwordPaint.setStrokeWidth(passwordWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();

        //画边框
        RectF rect = new RectF(0, 0, width, height);
        borderPaint.setColor(borderColor);
        canvas.drawRoundRect(rect, borderRadius, borderRadius, borderPaint);

        //画内容区域,与上面的borderPaint.setStyle(Paint.Style.FILL)对应, 防止原始输入内容显示出来
        RectF rectContent = new RectF(rect.left + defaultContentMargin, rect.top + defaultContentMargin, rect.right - defaultContentMargin, rect.bottom - defaultContentMargin);
        borderPaint.setColor(Color.WHITE);
        canvas.drawRoundRect(rectContent, borderRadius, borderRadius, borderPaint);

        //画分割线:分割线数量比密码数少1
        borderPaint.setColor(borderColor);
        borderPaint.setStrokeWidth(defaultSplitLineWidth);
        for (int i = 1; i < passwordLength; i++) {
            float x = width * i / passwordLength;
            canvas.drawLine(x, 0, x, height, borderPaint);
        }

        //画密码内容
        float px, py = height / 2;
        float halfWidth = width / passwordLength / 2;
        for (int i = 0; i < textLength; i++) {
            px = width * i / passwordLength + halfWidth;
            canvas.drawCircle(px, py, passwordWidth, passwordPaint);
        }
    }

5.定义“设置属性值”的方法,如下

public void setBorderWidth(int borderWidth) {
    this.borderWidth = borderWidth;
    borderPaint.setStrokeWidth(borderWidth);
    postInvalidate();
}

动态图

(如何制作gif动态图,请查看Android截图如何生成gif动态图)

自定义密码输入控件

项目源码

点此链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值