自定义View之验证码控件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjc_null/article/details/84860879

先上图镇贴

最近项目中有需要验证码,不过Android端的验证码一般都是手机短信,点击获取验证码,将请求向后台以及向短信验证码平台发送。短信平台将验证码发送到前端及后台,让前端输入验证码和后台进行比较。验证码的存在就是提高安全性,即使拿到账户和密码,也无法登陆。因为验证码是随机性的,唯一的,所以,提高了安全性。

但是,我们项目没有要求短信验证,因为账户不是手机号。所以,图片验证码就很有必要了。后台生成随机数,我再转换成图片的形式,给用户看到,让用户输入,和后台进行比较。相对来说,比较简单。但是也提高了安全性。废话少说,上代码。

我先说说我的思路,一般的图片验证码都有纯英文,英文加数字,纯数字等几种。我没要求太复杂的,只用了纯数字的那种,实现起来比较简单。

首先,我需要知道,图片验证码的样式,如图     大概就是这种样式的。

好了,定义了样式,就好做了。首先定义一个类,并让它继承View重写onDraw方法。

定义画笔,首先画一个矩形

        //初始化画笔
        paint.setColor(ColorUtil.AZURE);//设置画笔颜色
        //绘制矩形背景
        canvas.drawRect(0, 0, getWidth(), getHeight(), paint);

颜色自定义就可以,我使用的颜色值是#F0FFFF。其次就是定义矩形中间的文字了

        //如何设置不同字符的不同大小,不同颜色
        paint.setColor(randomColor());//设置画笔颜色
        paint.setTextSize(randomTextSize());//设置文字大小
        //绘制数字/文字
        canvas.drawText(codes, getWidth, getHeight, paint);

我考虑到,验证码图片,每一个字体颜色不一,大小不一,位置不同。所以,我将其颜色,大小,位置设置成动态。

randomColor()方法代码: rate默认为1;

        int red = random.nextInt(256) / rate;
        int green = random.nextInt(256) / rate;
        int blue = random.nextInt(256) / rate;
        return Color.rgb(red, green, blue);

randomTextSize()方法代码:size默认为1

        int textSize = random.nextInt(150) / size;
        if (textSize >= 80)
            return textSize;
        return 80;

准备工作完成,该写数据源了,因为我需要的验证码是四位数。如果是随机数,我将随机数设为10000,它最大不会超过四位数。给自定义View设一个点击事件,每点击一次让数据源变一次,这样就成功得到了随机数,验证码雏形。如果不是随机数,则将字符串个数控制在四位

        //获取数据源
        int i = random.nextInt(10000);

但是,我发现了一个问题,因为是随机数0-10000之间的,所以有可能会出现三位数俩位数,甚至是一位数,并且这样出来的随机数展示出来,无论怎么样变,它们的颜色都是一样的,因为它们是一个整体,所以我需要将这个整数进行拆分。如果是四位数,按照千位,百位,十位,个位进行拆分。如果是三位数,则千位为0,如果是两位数,则千位与百位分别为0.以此类推;我很有必要将它们拆开。由于语言的除法的特殊性,我们可以进行单独求数,首先先得到千位上的数,然后在得到百位上的数,如果不存在,则为0。之后做了一些改动,之前只能使用随机数,这次改动可以使用任意字符串包括随机数了,但是,随机数有可能会随机三位数、两位数、一位数甚至是负数,这就需要我们进行处理了。很简单,做一个判断,如果是纯数字,则就认为是随机数(验证码必须保证是四位哦)否则认为是字符串。

private String[] subString(Object codes) {
        String strCodes = setValueOf(codes);
        if (isInteger(codes)) {//判断是纯数字
            int thousand = getThousand(strCodes);//千位
            int hundred = getHundred(strCodes);//百位
            int ten = getTen(strCodes);//十位
            int one = getOne(strCodes);//个位
            String thousands = setValueOf(thousand);
            String hundreds = setValueOf(hundred);
            String tens = setValueOf(ten);
            String ones = setValueOf(one);
            return new String[]{thousands, hundreds, tens, ones};
        } else {//判断不是纯数字
            if (strCodes.length() > 0) {
                c1 = strCodes.substring(0, 1);
                c2 = strCodes.substring(1, 2);
                c3 = strCodes.substring(2, 3);
                c4 = strCodes.substring(3, 4);
            }
            return new String[]{c1, c2, c3, c4};
        }

    }

很简单,将初始值设为 4602 举例子。4602/1000我们得到4,4是千位,假如我的数据源为三位数,千位上没有,我们就得到0。

(number - thousand * 1000) / 100我们先计算number - thousand * 1000 我们已经得到thousand为4,4*1000得到4000,number为初始值4602,两者相减得到602,我们在使用602/100得到6,6是百位;我们用这种方法分别得到初始值的千位,百位,十位,个位;

我们在分别给每一个数字进行绘制,我们就能绘制出不同颜色,大小的随机数了。

改动,将原来的设置验证码大小颜色等放在外部,防止UI刷新,导致视图刷新。

/**
     * 设置字体内容,颜色以及位置
     *
     * @param codes     验证码内容
     * @param getWidth  验证码距离宽度
     * @param getHeight 验证码距离高度
     * @param canvas    画布
     * @param paint     画笔
     */
    private void drawText(String codes, int getWidth, int getHeight, Canvas canvas, Paint paint) {
        // 绘制数字/文字
        canvas.drawText(codes, getWidth, getHeight, paint);
    }

解决这些问题,基本上整个控件就完成了。但是会发现,一般的验证码图会有一些干扰线,我们还缺少干扰线,上代码

同样,干扰线,颜色,大小写在外部,防止UI刷新时,导致视图刷新。

 /**
     * 设置干扰线
     * @param canvas  画布
     * @param paint   画笔
     * @param startX  起点X坐标
     * @param startY  起点Y坐标
     * @param stopX   终点X坐标
     * @param stopY   终点Y坐标
     * @param strokeWidth 干扰线宽度
     */
    private void drawLine(Canvas canvas, Paint paint, int startX, int startY, int stopX, int stopY, int strokeWidth) {
        canvas.drawLine(startX, startY, stopX, stopY, paint);
    }

将验证码颜色,大下等属性放在设置验证码的时候,进行赋值,防止,每次更新UI同时,导致验证码视图的更新

/**
     * 设置验证码的颜色大小
     */
    private void setVerificationCodeStyle(){
        /**
         * 设置干扰线
         */
        startX = random.nextInt(NEXTINTWIDTH_ONE);
        startY = random.nextInt(NEXTINTHEIGHT_ONE);
        stopX = random.nextInt(NEXTINTWIDTH_THREE);
        stopY = random.nextInt(NEXTINTHEIGHT_TWO);
        startX1 = random.nextInt(NEXTINTWIDTH_ONE);
        startY1 = random.nextInt(NEXTINTHEIGHT_ONE);
        stopX1 = random.nextInt(NEXTINTWIDTH_TWO);
        stopY1 = random.nextInt(NEXTINTHEIGHT_TWO);
        startX2 = random.nextInt(NEXTINTWIDTH_THREE);
        startY2 = random.nextInt(NEXTINTHEIGHT_ONE);
        stopX2 = random.nextInt(NEXTINTWIDTH_TWO);
        stopY2 = random.nextInt(NEXTINTWIDTH_TWO);
        startX3 = random.nextInt(NEXTINTWIDTH_ONE);
        startY3 = random.nextInt(NEXTINTHEIGHT_ONE);
        stopX3 = random.nextInt(NEXTINTWIDTH_THREE);
        stopY3 = random.nextInt(NEXTINTHEIGHT_TWO);
        startX4 = random.nextInt(NEXTINTWIDTH_ONE);
        startY4 = random.nextInt(NEXTINTHEIGHT_ONE);
        stopX4 = random.nextInt(NEXTINTWIDTH_THREE);
        stopY4 = random.nextInt(NEXTINTHEIGHT_TWO);

        /**
         * 设置验证码颜色
         */
        color = randomColor();
        color2 = randomColor();
        color3 = randomColor();
        color4 = randomColor();

        /**
         * 设置验证码字体大小
         */
        size = randomTextSize();
        size2 = randomTextSize();
        size3 = randomTextSize();
        size4 = randomTextSize();
    }

通过线形绘制,绘制干扰线。这样基本上一个验证码控件已经完成了,我们再做一些细节的调整

同时,还进行了大小写的判断,进行大小写区别

 /**
     * 判断输入内容是否与展示内容相同
     * Equality相等
     *
     * @param charSequence
     * @return
     */
    public boolean isEquality(String charSequence, boolean isOpen) {
        String sequenceCode = null;//输入框输入内容
        String stringCode = null;//验证码随机数字
        if (null == charSequence || "".equals(charSequence)) {//判断输入内容为null
            if (onEqResultListener != null)
                onEqResultListener.onNull();
            return false;
        } else {//判断输入内容不为null
            if (isOpen) {//开启大小写区别
                sequenceCode = charSequence;
                stringCode = getCodeString();
            } else {//关闭大小写区别
                sequenceCode = charSequence.toLowerCase();//大写转小写
                stringCode = getCodeString().toLowerCase();//大写转小写
            }
            if (stringCode.equals(sequenceCode)) {//判断输入内容与随机数相等
                if (onEqResultListener != null)
                    onEqResultListener.onSuccess();
                return true;
            } else {//判断输入内容与随机数不相等
                onEqResultListener.onError();
                return false;
            }
        }
    }

使用String类型自带的大小写转换器进行转换,如果不开启大小写区别,则将输入的字符串与验证码中的字符串,全部转换为小写。

if (isOpen) {//开启大小写区别
                sequenceCode = charSequence;
                stringCode = getCodeString();
            } else {//关闭大小写区别
                sequenceCode = charSequence.toLowerCase();//大写转小写
                stringCode = getCodeString().toLowerCase();//大写转小写
            }


整体代码,在此借用大佬的"点点"背景样式,如图   

https://blog.csdn.net/ydxlt/article/details/50786076

public class VerificationView extends View {
    private static final String TAG = "VerificationView";

    /**
     * int min=10;
     * int max=99;
     * Random random = new Random();
     * int num = random.nextInt(max)%(max-min+1) + min;
     */
    private Object setCodes;//外部设置的验证码

    private Object code;
    private Random random;//随机数

    private Paint paint;//画笔
    private Rect rect;//定义矩形结构

    //干扰线
    private final int DISTURB_WIDTH = 200;
    private final int DISTURB_HEIGHT = 80;
    private final int STROKE_WIDTH = 1;

    private final int NEXTINTWIDTH_ONE = DISTURB_WIDTH / 1;
    private final int NEXTINTWIDTH_TWO = DISTURB_WIDTH * 2;
    private final int NEXTINTWIDTH_THREE = DISTURB_WIDTH / 1 * 2;

    private final int NEXTINTHEIGHT_ONE = DISTURB_HEIGHT / 1 * 2;
    private final int NEXTINTHEIGHT_TWO = DISTURB_HEIGHT / 1;

    //判断结果回调
    private OnEqResultListener onEqResultListener;
    private boolean isOpen;
    //int型验证码
    private int i;
    //验证码数组
    private String[] codesArray;
    //得到单个验证码
    private String c1;
    private String c2;
    private String c3;
    private String c4;
    private int DISTINGUISH;
    private int min = 1;
    private int max = 99;
    private boolean isRefereshing;
    //干扰条
    private int startX;
    private int startY;
    private int stopX;
    private int stopY;
    private int startX1;
    private int startY1;
    private int stopX1;
    private int stopY1;
    private int startX2;
    private int startY2;
    private int stopX2;
    private int stopY2;
    private int startX3;
    private int startY3;
    private int stopX3;
    private int stopY3;
    private int startX4;
    private int startY4;
    private int stopX4;
    private int stopY4;
    private int color1;
    private int color2;
    private int color3;
    private int color4;
    private int size;
    private int size2;
    private int size3;
    private int size4;
    private Paint mPointPaint;
    private List<PointF> mPoints = new ArrayList();

    //字体宽度
    public VerificationView(Context context) {
        this(context, null);
    }

    public VerificationView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public VerificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //创建画笔
        //Paint.ANTI_ALIAS_FLAG 抗锯齿
        if (paint == null)
            paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        // 初始化干扰点画笔
        if (mPointPaint == null)
            mPointPaint = new Paint();

        mPointPaint.setStrokeWidth(6);
        mPointPaint.setStrokeCap(Paint.Cap.ROUND); // 设置断点处为圆形

        //定义矩形结构
        if (rect == null)
            rect = new Rect();
        //随机数
        if (random == null)
            random = new Random();
    }

    /**
     * 绘制
     *
     * @param canvas 画布
     */
    @Override
    protected void onDraw(Canvas canvas) {
        //获取到验证码
        code = getVerificationCodes();
        setDraws(canvas, isRefereshing);
        isRefereshing = true;
        //super.onDraw(canvas);
    }

    /**
     * 拆分
     *
     * @param codes 验证码字符串
     * @return
     */
    private String[] subString(Object codes) {
        String strCodes = setValueOf(codes);
        if (isInteger(codes)) {//判断是纯数字
            int thousand = getThousand(strCodes);//千位
            int hundred = getHundred(strCodes);//百位
            int ten = getTen(strCodes);//十位
            int one = getOne(strCodes);//个位
            String thousands = setValueOf(thousand);
            String hundreds = setValueOf(hundred);
            String tens = setValueOf(ten);
            String ones = setValueOf(one);
            return new String[]{thousands, hundreds, tens, ones};
        } else {//判断不是纯数字
            if (strCodes.length() > 0) {
                c1 = strCodes.substring(0, 1);
                c2 = strCodes.substring(1, 2);
                c3 = strCodes.substring(2, 3);
                c4 = strCodes.substring(3, 4);
            }
            return new String[]{c1, c2, c3, c4};
        }
    }

    /**
     * 绘制
     *
     * @param canvas
     */
    private void setDraws(Canvas canvas, boolean refereshing) {

        mPoints.clear();
        // 生成干扰点坐标
        for (int i = 0; i < 150; i++) {
            PointF pointF = new PointF(random.nextInt(getWidth()) + 10, random.nextInt(getHeight()) + 10);
            mPoints.add(pointF);
        }


        // 产生干扰效果1 -- 干扰点
        for (PointF pointF : mPoints) {
            mPointPaint.setARGB(255, random.nextInt(200) + 20, random.nextInt(200) + 20, random.nextInt(200) + 20);
            canvas.drawPoint(pointF.x, pointF.y, mPointPaint);
        }


        //设置亚像素
        paint.setSubpixelText(true);
        paint.setAntiAlias(true);

        //初始化画笔
        paint.setColor(ColorUtil.AZURE);//设置画笔颜色
        //绘制矩形背景
        canvas.drawRect(0, 0, getWidth(), getHeight(), paint);


        paint.setColor(color1);
        //绘制画笔抗锯齿
        //设置干扰条 DISTURB_WIDTH / 1 ,  DISTURB_HEIGHT / 1 * 2
        drawLine(canvas, paint, startX, startY, stopX, stopY, STROKE_WIDTH + 1);

        paint.setColor(color2);
        //设置干扰条 DISTURB_WIDTH / 1 * 2 ,  DISTURB_HEIGHT / 1 * 2
        drawLine(canvas, paint, startX1, startY1, stopX1, stopY1, STROKE_WIDTH + 2);

        paint.setColor(color3);
        //设置干扰条 DISTURB_WIDTH / 1 ,  DISTURB_HEIGHT / 1 * 2
        drawLine(canvas, paint, startX2, startY2, stopX2, stopY2, STROKE_WIDTH + 1);

        paint.setColor(color4);
        //设置干扰条  DISTURB_WIDTH * 2 , DISTURB_HEIGHT / 1
        drawLine(canvas, paint, startX3, startY3, stopX3, stopY3, STROKE_WIDTH + 3);

        paint.setColor(color3);
        //设置干扰条  DISTURB_WIDTH / 1 * 2 , DISTURB_HEIGHT / 1
        drawLine(canvas, paint, startX4, startY4, stopX4, stopY4, STROKE_WIDTH + 2);


        //设置内边距
        int paddingLeft = getPaddingLeft();
        int paddingTop = getPaddingTop();
        int paddingRight = getPaddingRight();
        int paddingBottom = getPaddingBottom();


        rect.left = 50 + paddingLeft;
        rect.top = 66 + paddingTop;
        rect.right = 50 + paddingRight;
        rect.bottom = 0 + paddingBottom;

        //获取到单个验证码
        codesArray = subString(code);

        for (int i = 0; i < 4; i++) {
            paint.getTextBounds(codesArray[i], 0, codesArray[i].length(), rect);
        }

        //设置画笔的样式
        paint.setStyle(Paint.Style.STROKE);//空心
        //如何设置不同字符的不同大小,不同颜色
        paint.setColor(color1);//设置画笔颜色
        paint.setTextSize(size);//设置文字大小
        //设置内容、大小、颜色
        drawText(codesArray[0], getWidth() / 2 - rect.width() / 2 - 100, getHeight() / 2 + rect.height() / 2 + 10, canvas, paint);

        paint.setColor(color2);//设置画笔颜色
        paint.setTextSize(size2);//设置文字大小
        drawText(codesArray[1], getWidth() / 2 - rect.width() / 2 - 50, getHeight() / 2 + rect.height() / 2 + 10, canvas, paint);

        paint.setColor(color3);//设置画笔颜色
        paint.setTextSize(size3);//设置文字大小
        drawText(codesArray[2], getWidth() / 2 - rect.width() / 2, getHeight() / 2 + rect.height() / 2 + 10, canvas, paint);

        paint.setColor(color4);//设置画笔颜色
        paint.setTextSize(size4);//设置文字大小
        drawText(codesArray[3], getWidth() / 2 - rect.width() / 2 + 50, getHeight() / 2 + rect.height() / 2 + 10, canvas, paint);

    }

    /**
     * 外部设置验证码
     *
     * @param setCodes 验证码数据
     */
    public void setVerificationCodes(Object setCodes) {
        isRefereshing = false;
        if (setCodes.toString().length() < 4 || setCodes.toString().length() > 4) {//判断当开发者将验证码个数设置小于4位或者大于4位则将展示默认验证码
            this.setCodes = "ZHLl";
            return;
        }
        this.setCodes = setCodes;

        setVerificationCodeStyle();


        invalidate();
    }

    /**
     * 设置验证码的颜色大小
     */
    private void setVerificationCodeStyle() {
        /**
         * 设置干扰线
         */
        startX = random.nextInt(NEXTINTWIDTH_ONE);
        startY = random.nextInt(NEXTINTHEIGHT_ONE);
        stopX = random.nextInt(NEXTINTWIDTH_THREE);
        stopY = random.nextInt(NEXTINTHEIGHT_TWO);
        startX1 = random.nextInt(NEXTINTWIDTH_ONE);
        startY1 = random.nextInt(NEXTINTHEIGHT_ONE);
        stopX1 = random.nextInt(NEXTINTWIDTH_TWO);
        stopY1 = random.nextInt(NEXTINTHEIGHT_TWO);
        startX2 = random.nextInt(NEXTINTWIDTH_THREE);
        startY2 = random.nextInt(NEXTINTHEIGHT_ONE);
        stopX2 = random.nextInt(NEXTINTWIDTH_TWO);
        stopY2 = random.nextInt(NEXTINTWIDTH_TWO);
        startX3 = random.nextInt(NEXTINTWIDTH_ONE);
        startY3 = random.nextInt(NEXTINTHEIGHT_ONE);
        stopX3 = random.nextInt(NEXTINTWIDTH_THREE);
        stopY3 = random.nextInt(NEXTINTHEIGHT_TWO);
        startX4 = random.nextInt(NEXTINTWIDTH_ONE);
        startY4 = random.nextInt(NEXTINTHEIGHT_ONE);
        stopX4 = random.nextInt(NEXTINTWIDTH_THREE);
        stopY4 = random.nextInt(NEXTINTHEIGHT_TWO);

        /**
         * 设置验证码颜色
         */
        color1 = randomColor();
        color2 = randomColor();
        color3 = randomColor();
        color4 = randomColor();

        /**
         * 设置验证码字体大小
         */
        size = randomTextSize();
        size2 = randomTextSize();
        size3 = randomTextSize();
        size4 = randomTextSize();
    }

    /**
     * 得到验证码
     *
     * @return
     */
    public Object getVerificationCodes() {
        return setCodes;
    }

    /**
     * 设置字体颜色
     *
     * @return
     */
    private int randomColor() {
        return randomColor(1);
    }

    /**
     * 设置字体颜色
     *
     * @param rate
     * @return
     */
    private int randomColor(int rate) {
        int red = random.nextInt(256) / rate;
        int green = random.nextInt(256) / rate;
        int blue = random.nextInt(256) / rate;
        return Color.rgb(red, green, blue);
    }

    /**
     * 设置字体大小
     *
     * @return
     */
    private int randomTextSize() {
        return randomTextSize(1);
    }

    /**
     * 设置字体大小
     *
     * @param size
     * @return
     */
    private int randomTextSize(int size) {
        int textSize = random.nextInt(150) / size;
        if (textSize >= 80)
            return textSize;
        return 80;
    }

    /**
     * 获取验证码框内容
     *
     * @return
     */
    public String getCodeString() {
        return getSetiingCodes(code);
    }

    /**
     * 获取验证框内容
     *
     * @param obCodes
     * @return
     */
    public String getSetiingCodes(Object obCodes) {
        String codes = setValueOf(obCodes);
        return codes;
    }

    /**
     * 求四位数之和
     *
     * @param number 数据源初始值
     * @return
     */
    public int getSum(String number) {
        return getThousand(number) + getHundred(number) + getTen(number) + getOne(number);// 例如 4602 ~ 4+6+0+2=12
    }

    /**
     * 得到千位数
     *
     * @param numbers 数据源初始值千位
     * @return
     */
    public int getThousand(String numbers) {  //例如 4602/1000=4//千位数
        int number = setParseInt(numbers);
        return number / 1000; //得到千位数;
    }

    /**
     * 得到百位数
     *
     * @param numbers 数据源初始值百位
     * @return
     */
    public int getHundred(String numbers) {  //例如 4602-4*1000 = 602 602/100 = 6//百位数
        int number = setParseInt(numbers);
        return (number - getThousand(numbers) * 1000) / 100;//得到百位数;
    }

    /**
     * 得到十位数
     *
     * @param numbers 数据源初始值十位
     * @return
     */
    public int getTen(String numbers) {  //例如 4602-4*1000-6*100=4602-4000-600=2/10=0//十位数
        int number = setParseInt(numbers);
        return (number - getThousand(numbers) * 1000 - getHundred(numbers) * 100) / 10;// 得到十位数;
    }

    /**
     * 得到个位数
     *
     * @param numbers 数据源初始值个位
     * @return
     */
    public int getOne(String numbers) {
        //例如 4602-4*1000-6*100-0*10 = 4602-4000-600-0=2//个位数
        int number = setParseInt(numbers);
        return number - getThousand(numbers) * 1000 - getHundred(numbers) * 100 - getTen(numbers) * 10;// 求个位;
    }

    /**
     * 设置字体内容,颜色以及位置
     *
     * @param codes     验证码内容
     * @param getWidth  验证码距离宽度
     * @param getHeight 验证码距离高度
     * @param canvas    画布
     * @param paint     画笔
     */
    private void drawText(String codes, int getWidth, int getHeight, Canvas canvas, Paint paint) {
        // 绘制数字/文字
        canvas.drawText(codes, getWidth, getHeight, paint);
    }

    /**
     * 设置干扰线
     *
     * @param canvas      画布
     * @param paint       画笔
     * @param startX      起点X坐标
     * @param startY      起点Y坐标
     * @param stopX       终点X坐标
     * @param stopY       终点Y坐标
     * @param strokeWidth 干扰线宽度
     */
    private void drawLine(Canvas canvas, Paint paint, int startX, int startY, int stopX, int stopY, int strokeWidth) {
        paint.setStrokeWidth(strokeWidth);
        canvas.drawLine(startX, startY, stopX, stopY, paint);
    }

    /**
     * 将字符串转为int型
     *
     * @param text
     * @return
     */
    private int setParseInt(String text) {
        int i = Integer.parseInt(text);
        return i;
    }

    /**
     * 将Object类型转换成String类型
     *
     * @param object
     * @return
     */
    private String setValueOf(Object object) {
        String string = String.valueOf(object);
        return string;
    }


    /**
     * 判断输入内容是否与展示内容相同
     * Equality相等
     *
     * @param charSequence
     * @return
     */
    public boolean isEquality(String charSequence, boolean isOpen) {
        String sequenceCode = null;//输入框输入内容
        String stringCode = null;//验证码随机数字
        if (null == charSequence || "".equals(charSequence)) {//判断输入内容为null
            if (onEqResultListener != null)
                onEqResultListener.onNull();
            return false;
        } else {//判断输入内容不为null
            if (isOpen) {//开启大小写区别
                sequenceCode = charSequence;
                stringCode = getCodeString();
            } else {//关闭大小写区别
                sequenceCode = charSequence.toLowerCase();//大写转小写
                stringCode = getCodeString().toLowerCase();//大写转小写
            }
            if (stringCode.equals(sequenceCode)) {//判断输入内容与随机数相等
                if (onEqResultListener != null)
                    onEqResultListener.onSuccess();
                return true;
            } else {//判断输入内容与随机数不相等
                onEqResultListener.onError();
                return false;
            }
        }
    }


    /**
     * 判断输入内容是否与展示内容相同
     * Equality相等
     *
     * @param text
     * @return
     */
    public boolean isEquality(TextView text, boolean isOpen) {
        String charSequence = getTextToString(text);
        boolean equality = isEquality(charSequence, isOpen);
        return equality;
    }

    /**
     * 得到输入框输入的字符串
     *
     * @param textView
     * @return
     */
    public String getTextToString(TextView textView) {
        return textView == null || "".equals(textView.getText().toString().trim()) ? "" : textView.getText().toString().trim();
    }

    /**
     * 结果回调方法
     * result 结果
     *
     * @param charSequence
     * @param onEqResultListener
     */
    public void setEqOnResult(String charSequence, OnEqResultListener onEqResultListener) {
        this.onEqResultListener = onEqResultListener;
        isEquality(charSequence, isOpen());
    }

    /**
     * 结果回调方法
     * result 结果
     *
     * @param textView
     * @param onEqResultListener
     */
    public void setEqOnResult(TextView textView, OnEqResultListener onEqResultListener) {
        this.onEqResultListener = onEqResultListener;
        isEquality(textView, isOpen());
    }

    /**
     * 设置是否打开大小写区别
     *
     * @param isOpen
     */
    public void setOpenDifference(boolean isOpen) {
        this.isOpen = isOpen;
    }

    /**
     * 返回是否打开大小写区别
     *
     * @return
     */
    public boolean isOpen() {
        return isOpen;
    }

    /**
     * 判断是否是纯数字
     *
     * @param str
     * @return
     */
    public boolean isInteger(Object str) {
        String s = setValueOf(str);
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(s).matches();
    }

    //清空对象
    public void onDestroy() {
        if (paint != null)
            paint = null;
        if (rect != null)
            rect = null;
        if (random != null)
            random = null;
    }

    public interface OnEqResultListener {
        //验证码对比成功
        void onSuccess();

        //验证码对比失败
        void onError();

        //对比验证码为null
        void onNull();
    }

    /**
     * 把view转成图片
     *
     * @param view
     */
    private void viewSaveToImage(View view) {
        view.setDrawingCacheEnabled(true);
        view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
        view.setDrawingCacheBackgroundColor(Color.WHITE);

        // 把一个View转换成图片
        Bitmap cachebmp = viewConversionBitmap(view);

//        if (mBitmapDoneListener != null){
//            mBitmapDoneListener.bitmapDone(cachebmp);
//        }

        view.destroyDrawingCache();
    }

    /**
     * view转bitmap
     */
    public Bitmap viewConversionBitmap(View v) {
        int w = v.getWidth();
        int h = v.getHeight();

        Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmp);

        c.drawColor(Color.WHITE);
        /** 如果不设置canvas画布为白色,则生成透明 */

        v.layout(0, 0, w, h);
        v.draw(c);

        return bmp;
    }

    /**
     * 将char直接转化为byte,其值就是字符的ascii
     *
     * @param ch
     * @return
     */
    public byte charToByteAscii(char ch) {

        byte byteAscii = (byte) ch;

        return byteAscii;
    }

    /**
     * 将char直接转化成为int,其值就是字符的ASCII码
     *
     * @param ch
     * @return
     */
    public int charToIntegerAscii(char ch) {
        int intAscii = (int) ch;
        return intAscii;
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    public Bitmap getBitmap(View view) {
        Bitmap bitmap = null;
        int width = view.getRight() - view.getLeft();
        int height = view.getBottom() - view.getTop();
        final boolean opaque = view.getDrawingCacheBackgroundColor() != 0 || view.isOpaque();
        Bitmap.Config quality;
        if (!opaque) {
            switch (view.getDrawingCacheQuality()) {
                case DRAWING_CACHE_QUALITY_AUTO:
                case DRAWING_CACHE_QUALITY_LOW:
                case DRAWING_CACHE_QUALITY_HIGH:
                default:
                    quality = Bitmap.Config.ARGB_8888;
                    break;
            }
        } else {
            quality = Bitmap.Config.RGB_565;
        }
        bitmap = Bitmap.createBitmap(getResources().getDisplayMetrics(),
                width, height, quality);
        bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
        if (opaque) bitmap.setHasAlpha(false);
        boolean clear = view.getDrawingCacheBackgroundColor() != 0;
        Canvas canvas = new Canvas(bitmap);
        if (clear) {
            bitmap.eraseColor(view.getDrawingCacheBackgroundColor());
        }
        view.computeScroll();
        final int restoreCount = canvas.save();
        canvas.translate(-view.getScrollX(), -view.getScrollY());
        view.draw(canvas);
        canvas.restoreToCount(restoreCount);
        canvas.setBitmap(null);
        return bitmap;
    }


    // 获取指定Activity的截屏,保存到png文件
    public static Bitmap takeScreenShot(Activity activity) {
        // View是你需要截图的View
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap b1 = view.getDrawingCache();

        // 获取状态栏高度
        Rect frame = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        int statusBarHeight = frame.top;

        // 获取屏幕长和高
        int width = activity.getWindowManager().getDefaultDisplay().getWidth();
        int height = activity.getWindowManager().getDefaultDisplay().getHeight();
        // 去掉标题栏
        int hh = statusBarHeight + 50;

        Bitmap b = Bitmap.createBitmap(b1, 0, hh, width, height - hh);
        view.destroyDrawingCache();

        return b;
    }


    /**
     * 加载本地图片
     *
     * @param url 本地图片吗路径
     * @return
     */
    public Bitmap getLoacalBitmap(String url) {
        //获取File文件流对象
        FileInputStream fis = null;
        try {
            if (fis == null)
                fis = new FileInputStream(url);
            return BitmapFactory.decodeStream(fis);  ///把流转化为Bitmap图片

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private Bitmap loadBitmapFromView(View v) {
        int w = v.getWidth();
        int h = v.getHeight();
        Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmp);

        c.drawColor(Color.WHITE);
        /** 如果不设置canvas画布为白色,则生成透明 */

        v.layout(0, 0, w, h);
        v.draw(c);

        return bmp;
    }

    //然后View和其内部的子View都具有了实际大小,也就是完成了布局,相当与添加到了界面上。接着就可以创建位图并在上面绘制了:
    public void layoutView(View v, int width, int height) {
        // 指定整个View的大小 参数是左上角 和右下角的坐标
        v.layout(0, 0, width, height);
        int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
        int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
        /** 当然,measure完后,并不会实际改变View的尺寸,需要调用View.layout方法去进行布局。
         * 按示例调用layout函数后,View的大小将会变成你想要设置成的大小。
         */
        v.measure(measuredWidth, measuredHeight);
        v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
    }

    //设置验证码的随机字符串
    public String getRandomString(Random random, int length) {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(62);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }

}

在外部的调用,相对简单。我们需要再onCreate方法里面将验证码控件初始化

        //初始化验证码字符串
        String randomString = getRandomString(random, 4);
        //设置验证码源
        verificationView.setVerificationCodes(randomString);

getRandomString方法目的是设置随机字符串

    public String getRandomString(Random random, int length) {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(62);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }

当然,将初始化的代码也可写在验证码点击事件里面,已便得到,点击验证码图片,改变验证码字符串的目的

猜你喜欢

转载自blog.csdn.net/zjc_null/article/details/84860879