先上图镇贴
最近项目中有需要验证码,不过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();
}
当然,将初始化的代码也可写在验证码点击事件里面,已便得到,点击验证码图片,改变验证码字符串的目的