Android本地验证码的生成

android客户端生成本地验证码主要用来限制用户随意按请求按钮,其实该示例也是来对自定义view的练练手而已,先给出效果图吧

其中可定制:

*干扰线数目

*干扰点数目

*背景颜色

*验证码字体大小及字数

相信以上可以满足一般的需要了吧,不够的话可自行添加,下面就来讲实现的步骤了

继承view,重写构造方法,并初始化所需参数

public class ValidationCode extends View {

    private Paint mTextPaint;//文字画笔
    private Paint mPointPaint;//干扰点画笔
    private Paint mPathPaint;//干扰线画笔
    private Paint mBitmapPaint;//Bitmap图画笔
    private String mCodeString;//随机验证码
    private int mCodeCount;//验证码位数
    private float mTextSize;//验证码字符大小
    private int mPointNumber;//干扰点数目
    private int mLineNumber;//干扰线数目
    private int mBackGround;//背景颜色
    private float mTextWidth;//验证码字符串的显示宽度
    private static int mWidth;//控件的宽度
    private static int mHeight;//控件的高度
    private static Random mRandom = new Random();
    private Bitmap bitmap = null;//生成验证码图片

    public ValidationCode(Context context) {
        this(context, null);
    }

    public ValidationCode(Context context, AttributeSet attrs) {
        super(context, attrs);
        getAttrValues(context, attrs);
        init();
    }

    /**
     * 获取布局文件中的值
     */
    private void getAttrValues(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ValidationCode);
        mCodeCount = typedArray.getInteger(R.styleable.ValidationCode_CodeCount, 4);
        mPointNumber = typedArray.getInteger(R.styleable.ValidationCode_PointNumber, 100);
        mLineNumber = typedArray.getInteger(R.styleable.ValidationCode_LineNumber, 2);
        mTextSize = typedArray.getDimension(R.styleable.ValidationCode_CodeTextSize, 20);
        mBackGround = typedArray.getColor(R.styleable.ValidationCode_BackGround,Color.WHITE);
        typedArray.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));

    }

    /**
     * 初始化画笔
     */
    private void init() {
        //生成随机数字和字母组合
        mCodeString = getValidationCode(mCodeCount);
        //初始化文字画笔
        mTextPaint = new Paint();
        mTextPaint.setStrokeWidth(3);
        mTextPaint.setTextSize(mTextSize);
        //初始化干扰点画笔
        mPointPaint = new Paint();
        mPointPaint.setStrokeWidth(4);
        mPointPaint.setStrokeCap(Paint.Cap.ROUND);//设置断点处为圆形
        //初始化干扰线画笔
        mPathPaint = new Paint();
        mPathPaint.setStrokeWidth(5);
        mPathPaint.setColor(Color.GRAY);
        mPathPaint.setStyle(Paint.Style.STROKE);//设置画笔为空心
        mPathPaint.setStrokeCap(Paint.Cap.ROUND);//设置断点处为圆形
        //初始化Bitmap画笔
        mBitmapPaint = new Paint();
        mBitmapPaint.setColor(Color.RED);
        //取得验证码字符串显示的宽度值
        mTextWidth = mTextPaint.measureText(mCodeString);

    }
}

getAttrValues方法是用来配置自定义的属性,需要在 values 中新建 * attrs.xml * 文件,并加上自定义的属性,如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ValidationCode">
        <attr name="CodeCount" format="integer"/>
        <attr name="PointNumber" format="integer"/>
        <attr name="LineNumber" format="integer"/>
        <attr name="CodeTextSize" format="dimension"/>
        <attr name="BackGround" format="color"/>
    </declare-styleable>
</resources>

onMeasure方法则是在你需要对自定义的view的大小做出处理时,通过setMeasuredDimension设置该控件大小,下面给出重新定义的宽高代码块

/**
* 对view的宽高进行重新定义
*/
private int measureWidth(int measureSpec) {
    int result = 0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    if (specMode == MeasureSpec.EXACTLY) {
        result = specSize;
    } else {
        result = (int) (mTextWidth * 2.0f);
        if (specMode == MeasureSpec.AT_MOST) {
            result = Math.min(result, specSize);
        }
    }
    return result;
}

private int measureHeight(int measureSpec) {
    int result = 0;

    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    if (specMode == MeasureSpec.EXACTLY) {
        result = specSize;
    } else {
        result = (int) (mTextWidth / 1.5f);
        if (specMode == MeasureSpec.AT_MOST) {
            result = Math.min(result, specSize);
        }
    }
    return result;
}

重写onDraw(),绘制图形

  1. 绘制验证码文本字符串,干扰点,干扰线,生成验证码的bitmap图
/**
 * 获取验证码
 *
 * @param length 生成随机数的长度
 * @return
 */
public static String getValidationCode(int length) {
    String val = "";
    Random random = new Random();
    for (int i = 0; i < length; i++) {
        //字母或数字
        String code = random.nextInt(2) % 2 == 0 ? "char" : "num";
        //字符串
        if ("char".equalsIgnoreCase(code)) {
            //大写或小写字母
            int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
            val += (char) (choice + random.nextInt(26));
        } else if ("num".equalsIgnoreCase(code)) {
            val += String.valueOf(random.nextInt(10));
        }
    }
    return val;
}

/**
 * 生成干扰点
 */
private static void drawPoint(Canvas canvas, Paint paint) {
    PointF pointF = new PointF(mRandom.nextInt(mWidth) + 10, mRandom.nextInt(mHeight) + 10);
    canvas.drawPoint(pointF.x, pointF.y, paint);
}

/**
 * 生成干扰线
 */
private static void drawLine(Canvas canvas, Paint paint) {
    int startX = mRandom.nextInt(mWidth);
    int startY = mRandom.nextInt(mHeight);
    int endX = mRandom.nextInt(mWidth);
    int endY = mRandom.nextInt(mHeight);
    canvas.drawLine(startX, startY, endX, endY, paint);
}

/**
 1. 绘制验证码并返回
 */
private Bitmap generateValidate(){
    if(bitmap != null && !bitmap.isRecycled()){
        //回收并且置为null
        bitmap.recycle();
        bitmap = null;
    }
    //创建图片和画布
    Bitmap sourceBitmap = Bitmap.createBitmap(mWidth,mHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(sourceBitmap);

    //画背景颜色
    canvas.drawColor(mBackGround);

    //画上验证码
    int length = mCodeString.length();
    float charLength = mTextWidth / length;
    for (int i = 1; i <= length; i++) {
        int offsetDegree = mRandom.nextInt(15);
        //这里只会产生0和1,如果是1那么正旋转正角度,否则旋转负角度
        offsetDegree = mRandom.nextInt(2) == 1 ? offsetDegree : -offsetDegree;
        canvas.save();
        canvas.rotate(offsetDegree, mWidth / 2, mHeight / 2);
        //给画笔设置随机颜色
        mTextPaint.setARGB(255, mRandom.nextInt(200) + 20, mRandom.nextInt(200) + 20,
                mRandom.nextInt(200) + 20);
        canvas.drawText(String.valueOf(mCodeString.charAt(i - 1)), (i - 1) * charLength * 1.6f + 30,
                mHeight * 2 / 3f, mTextPaint);
        canvas.restore();
    }

    //产生干扰效果1 -- 干扰点
    for (int i = 0; i < mPointNumber; i++) {
        mPointPaint.setARGB(255, mRandom.nextInt(200) + 20, mRandom.nextInt(200) + 20,
                mRandom.nextInt(200) + 20);
        drawPoint(canvas, mPointPaint);
    }

    //生成干扰效果2 -- 干扰线
    for (int i = 0; i < mLineNumber; i++) {
        mPathPaint.setARGB(255, mRandom.nextInt(200) + 20, mRandom.nextInt(200) + 20,
                mRandom.nextInt(200) + 20);
        drawLine(canvas, mPathPaint);
    }

    canvas.save();
    return sourceBitmap;
}
  1. 实现onDraw()方法,绘画出验证码
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    //获取控件的宽和高
    mHeight = getHeight();
    mWidth = getWidth();

    if(bitmap == null){
        bitmap = generateValidate();
    }
    canvas.drawBitmap(bitmap,0,0,mBitmapPaint);
}

添加触摸事件,点击切换验证码

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mCodeString = getValidationCode(mCodeCount);
            bitmap = generateValidate();
            invalidate();
            break;
        default:
            break;
    }
    return super.onTouchEvent(event);
}

添加公开使用方法

我们总是需要提供给用户调用的方法,判断验证码是否一致之类的,方便用户进一步的操作,这里提供个几个方法

/**
 * 判断验证码是否一致
 *
 * @String CodeString
 * 这里忽略大小写
 */
public Boolean isEqualsIgnoreCase(String CodeString) {
    return mCodeString.equalsIgnoreCase(CodeString);
}

/**
 * 判断验证码是否一致
 * 不忽略大小写
 */
public Boolean isEquals(String CodeString) {
    return mCodeString.equals(CodeString);
}

/**
 * 外界控件调用刷新验证码图片
 */
public void refresh(){
    mCodeString = getValidationCode(mCodeCount);
    bitmap = generateValidate();
    invalidate();
}

以上就是生成本地验证码的一个简单的自定义view步骤,这里就给出源码地址,有需要的就去看看https://github.com/myloften/VerificationCodeSample

时间: 2025-01-18 16:27:51

Android本地验证码的生成的相关文章

Android开发——本地验证码的简易实现(防止暴力登录)

0.  前言   验证码无处不在,有人问我,你知道达芬奇密码下面是什么吗,对,答案就是达芬奇验证码. 验证码一个最主要的作用就是防止恶意暴力破解登录,防止不间断的登录尝试,有人说其实可以在服务器端对该终端进行登录间隔检测,如果间隔太短可以展示拒绝的姿态.但是还是本地验证码作用更加实在,可以减轻服务器端的压力.这篇将使用自定义View来实现一个如下效果的简易本地验证码.算是对自定义View知识的复习吧. 1.  布局结构   <RelativeLayout xmlns:android="ht

Android开发中验证码的生成

近期在做电商金融类的项目,验证码的生成方法不可缺少.先学习了一种.经过測试好用.从别处学习的代码,稍修改了一下可选择是否支持识别大写和小写.直接上代码. import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.EditText; import android.wid

生成本地验证码 _Android源码

这是我做的项目的一个小功能,实现了产生本地验证码的功能,点击验证码图片可以进行更换,其中还包含一些控件的美化,代码很简单,适合初学者. 下载地址:http://www.devstore.cn/code/info/721.html

随机图片验证码的生成

Python生成随机验证码,需要使用PIL模块. 安装: 1 pip3 install pillow 基本使用 1. 创建图片 1 2 3 4 5 6 7 8 9 from PIL import Image img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))   # 在图片查看器中打开 # img.show()   # 保存在本地 with open('code.png','wb') as f:     img.s

cordova-plugin-local-notifications发送Android本地消息

原文:cordova-plugin-local-notifications发送Android本地消息 1.GitHub源代码地址: https://github.com/katzer/cordova-plugin-local-notifications 2.参数说明: https://github.com/katzer/cordova-plugin-local-notifications/wiki/04.-Scheduling 3.事件说明: https://github.com/katzer/

android 导入自己的生成的jar,老是 could not find class

最近开始学习android,开发一个小项目,功能很简单,就是从服务器上获取数据,之后显示在手机上.打算把访问服务器的功能打包成一个jar文件.然后android 引入jar包. 在eclipse 里 新建了一个java项目.之后完成代码测试,打包成jar文件 都很顺利.引用到android项目中,调试总报错,could not find class . 折腾了几天,都没有解决,几乎试遍 了,网上的所有方法都不行.后来突然意识到,是不是java项目的jar 不能引用到android 中.后来新建一

android本地保存Cookie和还原到cookiestore

保存cookie,读取cookie以及判断cookie是否存在 ```java public class Local { private static SharedPreferences shared; public static void setShared(SharedPreferences shared) { Local.shared = shared; } public static void saveStrCookie(String cookie) { SharedPreference

ImageUtil(验证码数据生成工具类)

登录界面时,常常会使用到验证码图片生成,程序如下: package util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.

新版本ADT创建Android项目无法自动生成R文件解决办法

本人使用的是ADT是Version 23.0.2,支持Android 6.0之后的系统环境,最高版本23,在创建Android项目的时候,每次创建项目选择“Compile With”低于6.0版本的时候,都无法自动生成R文件,这个时候MainActivity文件报错,反复点击项目后执行“Clean”后,错误无法解 决,按照之前不生成R文件的办法解决不了,那怎么办呢?先分析错误产生的原因. 案例参考:新版本ADT创建Android项目无法自动生成R文件解决办法 | TeachCourse