Android本地驗(yàn)證碼的生成代碼
android客戶端生成本地驗(yàn)證碼主要用來(lái)限制用戶隨意按請(qǐng)求按鈕,其實(shí)該示例也是來(lái)對(duì)自定義view的練練手而已,先給出效果圖吧

其中可定制:
*干擾線數(shù)目
*干擾點(diǎn)數(shù)目
*背景顏色
*驗(yàn)證碼字體大小及字?jǐn)?shù)
相信以上可以滿足一般的需要了吧,不夠的話可自行添加,下面就來(lái)講實(shí)現(xiàn)的步驟了
繼承view,重寫(xiě)構(gòu)造方法,并初始化所需參數(shù)
public class ValidationCode extends View {
private Paint mTextPaint;//文字畫(huà)筆
private Paint mPointPaint;//干擾點(diǎn)畫(huà)筆
private Paint mPathPaint;//干擾線畫(huà)筆
private Paint mBitmapPaint;//Bitmap圖畫(huà)筆
private String mCodeString;//隨機(jī)驗(yàn)證碼
private int mCodeCount;//驗(yàn)證碼位數(shù)
private float mTextSize;//驗(yàn)證碼字符大小
private int mPointNumber;//干擾點(diǎn)數(shù)目
private int mLineNumber;//干擾線數(shù)目
private int mBackGround;//背景顏色
private float mTextWidth;//驗(yàn)證碼字符串的顯示寬度
private static int mWidth;//控件的寬度
private static int mHeight;//控件的高度
private static Random mRandom = new Random();
private Bitmap bitmap = null;//生成驗(yàn)證碼圖片
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));
}
/**
* 初始化畫(huà)筆
*/
private void init() {
//生成隨機(jī)數(shù)字和字母組合
mCodeString = getValidationCode(mCodeCount);
//初始化文字畫(huà)筆
mTextPaint = new Paint();
mTextPaint.setStrokeWidth(3);
mTextPaint.setTextSize(mTextSize);
//初始化干擾點(diǎn)畫(huà)筆
mPointPaint = new Paint();
mPointPaint.setStrokeWidth(4);
mPointPaint.setStrokeCap(Paint.Cap.ROUND);//設(shè)置斷點(diǎn)處為圓形
//初始化干擾線畫(huà)筆
mPathPaint = new Paint();
mPathPaint.setStrokeWidth(5);
mPathPaint.setColor(Color.GRAY);
mPathPaint.setStyle(Paint.Style.STROKE);//設(shè)置畫(huà)筆為空心
mPathPaint.setStrokeCap(Paint.Cap.ROUND);//設(shè)置斷點(diǎn)處為圓形
//初始化Bitmap畫(huà)筆
mBitmapPaint = new Paint();
mBitmapPaint.setColor(Color.RED);
//取得驗(yàn)證碼字符串顯示的寬度值
mTextWidth = mTextPaint.measureText(mCodeString);
}
}
getAttrValues方法是用來(lái)配置自定義的屬性,需要在 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方法則是在你需要對(duì)自定義的view的大小做出處理時(shí),通過(guò)setMeasuredDimension設(shè)置該控件大小,下面給出重新定義的寬高代碼塊
/**
* 對(duì)view的寬高進(jìn)行重新定義
*/
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;
}
重寫(xiě)onDraw(),繪制圖形
1、繪制驗(yàn)證碼文本字符串,干擾點(diǎn),干擾線,生成驗(yàn)證碼的bitmap圖
/**
* 獲取驗(yàn)證碼
*
* @param length 生成隨機(jī)數(shù)的長(zhǎng)度
* @return
*/
public static String getValidationCode(int length) {
String val = "";
Random random = new Random();
for (int i = 0; i < length; i++) {
//字母或數(shù)字
String code = random.nextInt(2) % 2 == 0 ? "char" : "num";
//字符串
if ("char".equalsIgnoreCase(code)) {
//大寫(xiě)或小寫(xiě)字母
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;
}
/**
* 生成干擾點(diǎn)
*/
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. 繪制驗(yàn)證碼并返回
*/
private Bitmap generateValidate(){
if(bitmap != null && !bitmap.isRecycled()){
//回收并且置為null
bitmap.recycle();
bitmap = null;
}
//創(chuàng)建圖片和畫(huà)布
Bitmap sourceBitmap = Bitmap.createBitmap(mWidth,mHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(sourceBitmap);
//畫(huà)背景顏色
canvas.drawColor(mBackGround);
//畫(huà)上驗(yàn)證碼
int length = mCodeString.length();
float charLength = mTextWidth / length;
for (int i = 1; i <= length; i++) {
int offsetDegree = mRandom.nextInt(15);
//這里只會(huì)產(chǎn)生0和1,如果是1那么正旋轉(zhuǎn)正角度,否則旋轉(zhuǎn)負(fù)角度
offsetDegree = mRandom.nextInt(2) == 1 ? offsetDegree : -offsetDegree;
canvas.save();
canvas.rotate(offsetDegree, mWidth / 2, mHeight / 2);
//給畫(huà)筆設(shè)置隨機(jī)顏色
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();
}
//產(chǎn)生干擾效果1 -- 干擾點(diǎn)
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;
}
2、實(shí)現(xiàn)onDraw()方法,繪畫(huà)出驗(yàn)證碼
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//獲取控件的寬和高
mHeight = getHeight();
mWidth = getWidth();
if(bitmap == null){
bitmap = generateValidate();
}
canvas.drawBitmap(bitmap,0,0,mBitmapPaint);
}
添加觸摸事件,點(diǎn)擊切換驗(yàn)證碼
@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);
}
添加公開(kāi)使用方法
我們總是需要提供給用戶調(diào)用的方法,判斷驗(yàn)證碼是否一致之類的,方便用戶進(jìn)一步的操作,這里提供個(gè)幾個(gè)方法
/**
* 判斷驗(yàn)證碼是否一致
*
* @String CodeString
* 這里忽略大小寫(xiě)
*/
public Boolean isEqualsIgnoreCase(String CodeString) {
return mCodeString.equalsIgnoreCase(CodeString);
}
/**
* 判斷驗(yàn)證碼是否一致
* 不忽略大小寫(xiě)
*/
public Boolean isEquals(String CodeString) {
return mCodeString.equals(CodeString);
}
/**
* 外界控件調(diào)用刷新驗(yàn)證碼圖片
*/
public void refresh(){
mCodeString = getValidationCode(mCodeCount);
bitmap = generateValidate();
invalidate();
}
以上就是生成本地驗(yàn)證碼的一個(gè)簡(jiǎn)單的自定義view步驟,這里就給出源碼地址,有需要的就去看看。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)滑塊拼圖驗(yàn)證碼功能
- Android自定義控件實(shí)現(xiàn)通用驗(yàn)證碼輸入框
- Android自定義View驗(yàn)證碼輸入框
- Android 使用fast-verification實(shí)現(xiàn)驗(yàn)證碼填寫(xiě)功能的實(shí)例代碼
- Android實(shí)現(xiàn)自定義驗(yàn)證碼輸入框效果(實(shí)例代碼)
- Android自定義控件實(shí)現(xiàn)短信驗(yàn)證碼自動(dòng)填充
- Android 自定義驗(yàn)證碼輸入框的實(shí)例代碼(支持粘貼連續(xù)性)
- Android實(shí)現(xiàn)點(diǎn)擊獲取驗(yàn)證碼60秒后重新獲取功能
- Android短信驗(yàn)證碼自動(dòng)填寫(xiě)實(shí)現(xiàn)代碼
- Android 簡(jiǎn)單的實(shí)現(xiàn)滑塊拼圖驗(yàn)證碼功能
相關(guān)文章
Android 組合控件實(shí)現(xiàn)布局的復(fù)用的方法
本篇文章主要介紹了Android 組合控件實(shí)現(xiàn)布局的復(fù)用的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08
Android利用Paint自定義View實(shí)現(xiàn)進(jìn)度條控件方法示例
這篇文章主要給大家介紹了關(guān)于Android利用Paint自定義View實(shí)現(xiàn)進(jìn)度條控件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位Android開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11
TextView長(zhǎng)按復(fù)制的實(shí)現(xiàn)方法(總結(jié))
下面小編就為大家?guī)?lái)一篇TextView長(zhǎng)按復(fù)制的實(shí)現(xiàn)方法(總結(jié))。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Android通訊錄開(kāi)發(fā)之刪除功能的實(shí)現(xiàn)方法
這篇文章主要介紹了Android通訊錄開(kāi)發(fā)之刪除功能的實(shí)現(xiàn)方法,有需要的朋友可以參考一下2014-01-01
Android應(yīng)用中實(shí)現(xiàn)跳轉(zhuǎn)外部瀏覽器打開(kāi)鏈接功能
在開(kāi)發(fā)Android應(yīng)用程序時(shí),有時(shí)候我們需要讓用戶跳轉(zhuǎn)到外部瀏覽器打開(kāi)特定的鏈接,例如打開(kāi)一個(gè)網(wǎng)頁(yè)、下載文件等,本文將介紹如何在Android應(yīng)用中實(shí)現(xiàn)跳轉(zhuǎn)外部瀏覽器打開(kāi)鏈接的功能,感興趣的朋友一起看看吧2024-06-06

