自定义控件之-----密码框

很多时候我们会使用到输入密码并隐藏显示,这里我仿照支付宝密码输入写了下面这个控件。压缩gif后密码框竖线显示失真

另外,我们可能会需要使用自己的键盘而不是采用系统键盘。这里我做了简单的  密码输入控件。

控件效果如下:

 

附上密码框源码源码:

package com.example.myapplication.coustom;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * email:1040152329@qq.com
 * Created by gold on 2019/11/6
 * Describe:
 **/
public class PasswordInputView extends View{
    public PasswordInputView(Context context) {
        super(context);
        initPaint();
    }

    public PasswordInputView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPaint();
    }

    public PasswordInputView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }
    private void initPaint() {

        paint=new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(6f);
        paint.setAntiAlias(true);
    }

    private Paint paint;
    private int mHeight;

    /**
     * 线宽
     */
    private float strokeWidth=1.5f;

    /**
     * 获取用户输入了第几位密码,根据位数绘制圆点代替,默认没有输入为0,不会绘制圆点
     */
    private int numberPath=0;
    /**
     * passwordsBoxsNumbers 密码框数量,可动态设置,默认为6个,可根据需求更改
     */
    private int passwordsBoxsNumbers =6;



    public Paint getPaint() {
        return paint;
    }

    public void setPaint(Paint paint) {
        this.paint = paint;
    }

    public int getNumberPath() {
        return numberPath;
    }

    public void setNumberPath(int numberPath) {
        this.numberPath = numberPath;
    }
    private int radius=10;

    public void setRadius(int radius) {
        this.radius = radius;
    }

    public void setPasswordsBoxsNumbers(int passwordsBoxsNumbers) {
        this.passwordsBoxsNumbers = passwordsBoxsNumbers;
    }

    /**
     * 间隔宽度设置为高
     * startX 初始X
     */
    private int startX;
    /**
     * 间隔宽度设置为高
     * startY 初始Y
     */
    private int startY;
    private int endY;
    /**
     * centerCircleX 画圆点的中心点X坐标
     */
    private int centerCircleX;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mHeight=getHeight();
        int reHeight=mHeight*2/3;//控件内容高
        int reWidth=reHeight*passwordsBoxsNumbers;//控件内容宽,是passwordsBoxsNumbers倍高
        int distance =(getWidth()-reWidth)/2;
        startX=distance;
        startY=(mHeight-reHeight)/2;
        endY=mHeight-startY;
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.parseColor("#CDC9C9"));
        paint.setStrokeWidth(2*strokeWidth);
        //画粗外框矩形
        canvas.drawRect(distance,startY,distance+reWidth,endY,paint);
        //画细竖线
        for (int i = 0; i < passwordsBoxsNumbers-1 ; i++) {
            paint.setStrokeWidth(strokeWidth);
            startX+=reHeight;
            canvas.drawLine(startX,startY,startX,endY,paint);
        }

        //准备画圆点
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.parseColor("#000000"));
        centerCircleX = distance+reHeight/2;
        for (int j = 0; j < numberPath; j++) {
            canvas.drawCircle(centerCircleX,mHeight/2,radius,paint);
            centerCircleX+=reHeight;
        }
    }



    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode=MeasureSpec.getMode(widthMeasureSpec);
        int widthSize=MeasureSpec.getSize(widthMeasureSpec);
        int heightMode=MeasureSpec.getMode(heightMeasureSpec);
        int heightSize=MeasureSpec.getSize(heightMeasureSpec);
        if (widthMode==MeasureSpec.AT_MOST&&heightMode==MeasureSpec.AT_MOST){
            setMeasuredDimension(800,80);
        }else if (widthMode==MeasureSpec.AT_MOST) {
            setMeasuredDimension(800,heightSize);
        }else if (heightMeasureSpec==MeasureSpec.AT_MOST){
            setMeasuredDimension(widthSize,80);
        }


    }

    private StringBuffer password=new StringBuffer("");

    public StringBuffer notify(String numberStr){
        if (numberStr.equals("×")){//点击了删除按钮
            if (password.length()>0){
                password.deleteCharAt(password.length()-1);
            }
        }else{
            if (password.length()<6){
                password.append(numberStr);
            }
        }
        numberPath=password.length();
        Log.e("onNumberSelected",numberStr+"    "+numberPath+"   "+password.toString());
        invalidate();

        /*if (password.length()==6){
            // TODO: 2019/11/6   长度等于密码长度时可以做自己的校验操作
        }*/
        return password;
    }

}

 

 

数字键盘贴出源码:

package com.example.myapplication.coustom;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * email:1040152329@qq.com
 * Created by gold on 2019/11/6
 * Describe:
 **/
public class PasswordsInputKeyBoardView extends View {
    public PasswordsInputKeyBoardView(Context context) {
        super(context);
    }

    public PasswordsInputKeyBoardView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PasswordsInputKeyBoardView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 需要绘制的资源数据
     */
    private String [] numbers={"1","2","3","4","5","6","7","8","9","n","0","×"};
    /**
     * 行高
     */
    private float singleHeight;
    /**
     * 列宽
     */
    private float singleWidth;
    /**
     * 起始X,Y值,方便绘制网格线
     */
    private float startX;
    private float startY;
    /**
     * 绘制数字时的X位置
     */
    private float x;
    /**
     * 网格线颜色,和按下时背景颜色相同
     */
    private String gridLineOrPressColor="#cccccc";
    /**
     * 数字颜色
     */
    private String textNumberColor="#000000";
    /**
     * 默认背景颜色
     */
    private String defaultBackgroundColor="#ffffff";

    public void setDefaultBackgroundColor(String defaultBackgroundColor) {
        this.defaultBackgroundColor = defaultBackgroundColor;
    }

    /**
     * 绘制数字大小
     */
    private int textSize=60;
    /**
     * 网格线宽
     */
    private float strokeWidth=1.5f;

    public void setNumbers(String[] numbers) {
        this.numbers = numbers;
    }

    public void setGridLineOrPressColor(String gridLineOrPressColor) {
        this.gridLineOrPressColor = gridLineOrPressColor;
    }

    public void setTextNumberColor(String textNumberColor) {
        this.textNumberColor = textNumberColor;
    }

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

    public void setStrokeWidth(float strokeWidth) {
        this.strokeWidth = strokeWidth;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        initPaint(canvas);
        singleWidth=getWidth()/3;
        singleHeight=getHeight()/4;


        //画背景颜色
        mPaint.setColor(Color.parseColor(defaultBackgroundColor));
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawRect(0,0,getWidth(),getHeight(),mPaint);

        //根据是否按下,变换背景颜色
        if (isPressed){
            mPaint.setColor(Color.parseColor(gridLineOrPressColor));
            mPaint.setStyle(Paint.Style.FILL);
            //绘制按下时背景(按下的那一格)
            canvas.drawRect((float)pressedRectPosition.get(0),(float)pressedRectPosition.get(1),
                    (float)pressedRectPosition.get(2),(float)pressedRectPosition.get(3),mPaint);
        }else if (pressedRectPosition!=null&&pressedRectPosition.size()!=0){
            mPaint.setColor(Color.parseColor(defaultBackgroundColor));
            mPaint.setStyle(Paint.Style.FILL);
            //绘制离开时背景(按下的那一格)
            canvas.drawRect((float)pressedRectPosition.get(0),(float)pressedRectPosition.get(1),
                    (float)pressedRectPosition.get(2),(float)pressedRectPosition.get(3),mPaint);
            pressedRectPosition.clear();
        }

        mPaint.setColor(Color.parseColor(gridLineOrPressColor));
        for (int i = 0; i < 5 ; i++) {
            //画横线
            canvas.drawLine(startX,startY,startX+getWidth(),startY,mPaint);
            startY+=singleHeight;
        }
        //重置
        startX=0;
        startY=0;
        for (int j = 0; j < 4 ; j++) {
            //画竖线
            canvas.drawLine(startX,startY,startX,startY+getHeight(),mPaint);
            startX+=singleWidth;
            //画数据
        }
        //重置
        startX=0;
        startY=0;
        float y=0;
        mPaint.setColor(Color.parseColor(textNumberColor));
        mPaint.setFakeBoldText(true);
        mPaint.setTextSize(textSize);
        for (int i = 0; i < 4 ; i++) {
            //画数据,一行一行画
            for (int j = 0; j < 3; j++) {
                if (j==0){
                    //获取文字宽
                    float textWidth=mPaint.measureText(numbers[i*3+j]);
                    x=singleWidth/2-textWidth/2;
                }
                if (i==0){
                    //获取文字高
                    Rect re=new Rect();
                    mPaint.getTextBounds(numbers[i*3+j],0,1,re);
                    int textHeight=re.height();
                    y=singleHeight/2+textHeight/2;
                }
                if (!numbers[i*3+j].equals("n")){
                    canvas.drawText(numbers[i*3+j],x,y,mPaint);
                }
                //X内层变化(放里面)
                x+=singleWidth;
            }
            //Y外层变化(放外面)
            y+=singleHeight;
        }


    }
    private Paint mPaint;
    private void initPaint(Canvas canvas) {
        mPaint=new Paint();
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setAntiAlias(true);
    }
    //是否按下
    private boolean isPressed=false;
    //
    //表示记录按下时所在矩形框位置的集合
    private List pressedRectPosition=new ArrayList();
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action=event.getAction();
        switch(action){
            case MotionEvent.ACTION_DOWN:
                //记录按下时刻的X,Y
                float downX=event.getX();
                float downY=event.getY();
                //边界值 (left,top,right,bottom)对应(minX,minY,maxX,maxY)
                float minX=0;
                float minY=0;
                float maxX=getWidth()/3;
                float maxY=getHeight()/4;
                for (int i = 0; i < 4; i++) {
                    //确定点击事件所在行
                    if (maxY>downY&&downY>minY){
                        for (int j = 0; j < 3; j++) {
                            //确定点击事件所在列
                            if (maxX>downX&&downX>minX&&(i*3+j)!=9){
                                if (mOnNumberSelectedListener!=null){
                                    mOnNumberSelectedListener.onNumberSelected(numbers[i*3+j]);
                                }
                                //按下是所在矩形位置 (minX,minY,maxX,maxY);
                                //按下状态为true
                                isPressed=true;
                                pressedRectPosition.add(minX);
                                pressedRectPosition.add(minY);
                                pressedRectPosition.add(maxX);
                                pressedRectPosition.add(maxY);
                                invalidate();
                            }
                            minX=maxX;
                            maxX=maxX+singleWidth;
                        }
                    }
                    minY=maxY;
                    maxY=maxY+singleHeight;
                }
                break;
            case MotionEvent.ACTION_MOVE:

                break;
            case MotionEvent.ACTION_UP:
                isPressed=false;
                invalidate();
                break;
        }
        return true;
    }

    private OnNumberSelectedListener mOnNumberSelectedListener;

    public void setmOnNumberSelectedListener(OnNumberSelectedListener mOnNumberSelectedListener) {
        this.mOnNumberSelectedListener = mOnNumberSelectedListener;
    }

    /**
     * 点击事件接口
     */
    public interface OnNumberSelectedListener{
        void onNumberSelected(String numberStr);
    }
}

 

两控件合使用,源码已提供接口。

在activity页面调用:

passwordsInputKeyBoardView.setmOnNumberSelectedListener(new PasswordsInputKeyBoardView.OnNumberSelectedListener() {
    @Override
    public void onNumberSelected(String numberStr) {
        text.setText(passwordInputView.notify(numberStr));
    }
});

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值