自定义View之验证码控件

本文详细介绍了一种自定义验证码控件的实现方法,包括随机数生成、颜色和大小动态设置、干扰线绘制等关键步骤,有效提高了应用的安全性和用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上图镇贴

最近项目中有需要验证码,不过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.youkuaiyun.com/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();
    }

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

.Net 验证码控件 操作简单,使用方便参数使用有详细介绍 拖入即可应用!!!!!! 添加到工具箱的步骤 1.将 Vincent.AutoAuthCode.dll 添加到项目的 Bin文件目录下 2.右键点击 Bin 目录 选择添加引用 找到添加的 Bin文件目录下 Vincent.AutoAuthCode.dll 3.在工具栏中,右键点击 常规 选项卡 再点击 选择项 4.在弹出的对话框中的右下方 点击 浏览 找到 Bin文件目录下 Vincent.AutoAuthCode.dll 打开 点击 确定 在 工具箱 的 常规选项 看到 AutcCode 控件 直接拖到要使用验证码的页面位置 即可。 页面的点击事件会触发验证,无需后台代码验证 一、控件特点: 1、使用方便,只需要从工具栏直接拖到页面即可自动验证,零代码使用。 2、自动完成客户端以及服务器的验证码验证,Ajax验证,随用户输入即时 验证并友好提示。 3、可自定义验证码图片外观。 4、有水平方向垂直方向两种方式选择。 5、有数字、小写字母、大写字母三种及任意两种组合、三种组合字符选择。 6、兼容IE及FireFox。 二、使用说明。 1、属性。 IsMatch:指示用户输入的验证码是否正确 TextControlWidth:文本框控件宽度 NextImgText:提示更换图片信息,该提示信息同时显示于图片上面及图片左边 IsShowNextImgText:是否在图片左边显示提示更换图片信息 EnableNextImgText:是否充许换一张图片 ErrorShowType:验证码错误显示方式 CodeStringType:验证码字符类型,组合枚举值,例如CodeStringTypes.Number|CodeStringTypes.LowerLetter CodeStringLength:验证码字符长度,最少为4 ImageType:验证码图像类型 IsMatchCase:验证码验证时是否区分大小写 LayoutDirection":控件各部分排列方向,排列的部分包括文本框、图片、"换一张图片"文本 EnableClientValidate:是否使用客户端脚本验证,验证内容包括是否为空、长度是否正确 ImageStyle:验证码图像样式 如: TextControlWidth="90px" 设置 输入验证码的文本框宽度 其中ImageStyle为复类属性,其公开属性如下: ImageStyle-ImgBgColor:图片背景色 ImageStyle-ImgNoiseColor:图片噪声颜色 ImageStyle-ImgBorderColor"图片边框颜色 ImageStyle-TextColor1:文本颜色 ImageStyle-TextColor2:文本颜色2(如果文本为单色则无效) ImageStyle-TextFontSize:文本字体大小,以像素(pix)为单位,验证码图像大小根据此而变化,如果ImgSize大于由该值指定的大小,则图像大小为ImgSize ImageStyle-ImgSize:验证码图像大小,以像素(pix)为单位,如果TextFontSize指定的大小大于该值,则图像大小为TextFontSize指定的大小 ImageStyle-Width:验证码图像大小的宽度,以像素(pix)为单位,如果TextFontSize指定的大小大于该值,则图像大小为TextFontSize指定的大小 ImageStyle-Height:验证码图像大小的高度,以像素(pix)为单位,如果TextFontSize指定的大小大于该值,则图像大小为TextFontSize指定的大小 如: ImageStyle-Width=70 设置验证码图像大小的宽度 (值必须是整数) ImageStyle-ImgBgColor=#1D3647 图片背景色 (值不要添加单、双引号 [''," "])
功能介绍:  为网页编程人员提供能够自动生成验证码图像并验证网页访问者输入的Web控件,具体功能如下:1. 提供简单易用的设计时所见即所得的可视化设置方式,并且支持设计时验证码图像效果与特效属性设置的实时联动体现,极大地提高程序员的工作效率;2. 对验证码图像的包括残影、打散、风化、旋转、斜变等多种图形学图像处理特效以及对各种特效的三个程度等级的灵活控制能力,让程序员在轻松应对基于OCR的恶意识别攻击的情况下,还能有充分的余地考虑验证码图像外观的美化问题;3. 提供灵活的中文诗词、中文单字、英文大小写字母、阿拉伯数字等丰富的验证码生成字源混合控制以及对于字数和字体的自定义控制,让程序员在面对不同客户以及网页访问者的特殊要求的同时仍能从容兼顾良好的用户体验;4. 保留对抗OCR的经典的点、线干扰特效以及三个程度等级的灵活控制,并采用色调匹配技术在保证原有的OCR对抗效果的同时加入了更加美观的彩色点、线效果,留给程序员更多的选择;5. 无刷新页面验证。更好地适用于需要填写大量信息的页面验证,有效地避免由于因突发性网络原因导致的验证码图像的无法下载,而使网页用户必须刷新页面而重填其它信息的窘境。运行环境:1. Microsoft Windows XP Professional2. Microsoft Visual Studio 20053. Microsoft .NET Framework V2.04. Microsoft Internet Information Services (IIS) V5.1(注意在子安装选项中选中FrontPage 2000服务器扩展)常见问答:1. 如何将本控件添加到Microsoft Visual Studio 2005的IDE中?a) 在Microsoft Visual Studio 2005中打开源代码的工程文件,重新编译,生成vcg.dll;b) 在工具箱(Toolbox)面板上单击右键,选择Choose Items…菜单,在弹出来的Choose ToolBox Items属性面板中,点击Browse…找到并选定vcg.dll控件。该控件即被添加到工具箱;2. 如何使用本控件?a) 确认需要添加本控件的网页为aspx页面。在IIS管理器中将网站属性的ASP.NET version选中为2.0,并在网站虚拟目录属性的“安全”选项卡中添加ASP.NET用户,赋予写入权限;b) 在Microsoft Visual Studio 2005中打开相应的网站,并打开相应的aspx页面文件(在本文中以Default.aspx为例),进入Design编辑模式;c) 从工具箱将之前添加的vcg控件拖到Default.aspx页面上。此时页面上的拖放位置应该出现一个带有文字内容的图片框,说明vcg控件已经被正确添加到页面;d) 现在可以像修改其它标准控件一样通过鼠标对控件进行拖动、缩放等修改,还可以在属性栏对控件进行进一步的细节设置。主要包括针对验证码图像的特效控制和针对验证码本身的文字控制两个方面。具体内容请参考本控件的使用手册;e) 在Default.aspx中新增Web控件Button:btnValidate,作为验证促发;在Default.aspx中新增Web控件TextBox:textCode,作为验证码输入;在Default.aspx中新增Web控件Lable:lblMessage,作为验证结果输出;f) 在Default.aspx.cs中添加验证函数:protected void btnValidate_Click(object sender, EventArgs e){ string code = “”; try { //真正的验证码存储在Session[“Code”]中,需要的只是对验证码输入和该值进行比较。 //(如果属性栏中“文字控制”属性卡下的“SessionCode”默认属性值“Code”改变, //则在代码中的Session[”Code”]中引号内的值也必须手工修改成与属性值一致的字符串。) code = Session[”Code”].ToString(); } catch (Exception ex
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值