自定義View之驗證碼控制元件
先上圖鎮貼
最近專案中有需要驗證碼,不過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();
}
當然,將初始化的程式碼也可寫在驗證碼點選事件裡面,已便得到,點選驗證碼圖片,改變驗證碼字串的目的