Android拆輪子系列之寫驗(yàn)證碼控件的方法
前言
先看看效果
怎么樣不錯(cuò)吧?別急下面我就一步一步的教你實(shí)現(xiàn)。
用到的知識(shí)點(diǎn)總結(jié):
1.Canvas和pint的使用,我們用它畫點(diǎn),線,字
2.View的基本用法
其實(shí)做這個(gè)東西還是很簡(jiǎn)單的,總體思路步驟如下:
1.準(zhǔn)備一個(gè)Canvas。
2.向Canvas里面畫幾條斜杠。
3.向canvas里面畫100個(gè)小點(diǎn)。
4.隨機(jī)生成4個(gè)數(shù)字,然后畫在canvas里面。
其實(shí)就是這么簡(jiǎn)單,沒什么深?yuàn)W的。
開始寫編碼
1.首先我們要重寫View
既然我們要畫驗(yàn)證碼,那么我們就需要準(zhǔn)備畫筆(paint)和畫板(canvas)代碼如下:
/** * Created by YuYuanDa on 2016-10-10. */ public class CheckView extends View implements View.OnClickListener{ private Context mContext; private Paint mPaint ; // 畫筆 public CheckView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; initPaint(); //設(shè)置點(diǎn)擊時(shí)間,當(dāng)自身收到點(diǎn)擊應(yīng)該更新數(shù)字(即重新?lián)Q驗(yàn)證碼數(shù)字) setOnClickListener(this); } /** * 初始化paint(畫筆) */ private void initPaint(){ mPaint = new Paint(); mPaint.setAntiAlias(true);//加上抗鋸齒 mPaint.setTextSize(Config.TEXT_SIZE);//設(shè)置字體大小 mPaint.setStrokeWidth(3);線寬 mPaint.setColor(Config.TEXTCOLOR);//設(shè)置字體顏色顏色 //設(shè)置粗體的字體 Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD); mPaint.setTypeface( font ); } @Override public void onClick(View v) { //在這里面更新,重新?lián)Q一套驗(yàn)證碼字符 } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(Config.COLOR);//先畫一個(gè)背景顏色 } } /** * 配置字段 */ class Config{ // 點(diǎn)數(shù)設(shè)置 public static final int POINT_NUM = 100; // 線段數(shù)設(shè)置 public static final int LINE_NUM = 2; //設(shè)置驗(yàn)證碼背景顏色 public static final int COLOR = Color.rgb(247,230,220); //隨機(jī)字符長(zhǎng)度長(zhǎng)度 public static int TEXT_LENGTH = 4; //設(shè)置驗(yàn)證碼字體大小 public static int TEXT_SIZE = 40; //驗(yàn)證碼字體顏色 public static final int TEXTCOLOR = Color.rgb(255,101,1); }
好了,上面的代碼中,我們自定義一個(gè)CheckView類,并準(zhǔn)備了以下材料:
1.為了更新數(shù)據(jù)我們?cè)O(shè)置了點(diǎn)擊事件setOnClickListener(this);,
2.Config類是為我們準(zhǔn)備配置信息,
3.new 出一支paint(畫筆),并添加相關(guān)參數(shù)。
4.準(zhǔn)備了畫板canvas(在ondraw()方法中),下面我們將在ondraw()方法中畫東西了。
2.接下來我們開始畫線、點(diǎn)、字。
畫線代碼如下:
private void drawLine(Canvas canvas){ for (int i = 0; i < Config.LINE_NUM; i++) {//根據(jù)LINE_NUM畫線的數(shù)量,你可以自己配置 //劃線 int[] line = getLine(getHeight(), getWidth()); canvas.drawLine(line[0], line[1], line[2], line[3], mPaint); } } public static int[] getLine(int height, int width) { int[] tempCheckNum = {0, 0, 0, 0}; for (int i = 0; i < 4; i += 2) { tempCheckNum[i] = (int) (Math.random() * width); tempCheckNum[i + 1] = (int) (Math.random() * height); } return tempCheckNum; }
下面我們來講一下canvas.drawLine()方法。先看看源碼:
public void drawLine (float startX, float startY, float stopX, float stopY, Paint paint){ }
參數(shù)說明:
startX:起始端點(diǎn)的X坐標(biāo)。
startY:起始端點(diǎn)的Y坐標(biāo)。
stopX:終止端點(diǎn)的X坐標(biāo)。
stopY:終止端點(diǎn)的Y坐標(biāo)。
paint:繪制直線所使用的畫筆
看到?jīng)],其實(shí)畫線就需要paint和2個(gè)起始點(diǎn)。在getline()方法中,for循環(huán)其實(shí)就循環(huán)了2次, math.random()取值范圍是:0.0~1.0 ,所以可以看出,Math.random() * width/heigth隨機(jī)的在view中取4個(gè)點(diǎn)作為2個(gè)點(diǎn)的取值,然后 canvas.drawLine()畫出來。
畫點(diǎn)代碼如下:
private void drawCircle(Canvas canvas){ // 繪制小圓點(diǎn) int[] point; for (int i = 0; i < Config.POINT_NUM; i++) {//根據(jù)POINT_NUM畫點(diǎn)的數(shù)量,你可以自己配置 //畫點(diǎn) point = getPoint(getHeight(), getWidth()); canvas.drawCircle(point[0], point[1], 1, mPaint); } } /** * 隨機(jī)產(chǎn)生點(diǎn)的圓心點(diǎn)坐標(biāo) * @param height 傳入CheckView的高度值 * @param width 傳入CheckView的寬度值 * @return */ public static int[] getPoint(int height, int width) { int[] tempCheckNum = {0, 0, 0, 0}; tempCheckNum[0] = (int) (Math.random() * width); tempCheckNum[1] = (int) (Math.random() * height); return tempCheckNum; }
下面我們來講一下canvas.drawCircle()方法
基本語(yǔ)法
public void drawCircle (float cx, float cy, float radius, Paint paint)
參數(shù)說明
cx:圓心的x坐標(biāo)。
cy:圓心的y坐標(biāo)。
radius:圓的半徑。
paint:繪制時(shí)所使用的畫筆。
看了上面的基本語(yǔ)法,大家應(yīng)該明白了,畫圓只需要圓心,半徑和paint就行。在getPoint()方法中,我們依舊利用Math.random() * width/height方法在View中隨機(jī)的取2個(gè)點(diǎn)作為圓心。
畫文字代碼如下:
下面我們就來講最后一步畫文字。這個(gè)比較麻煩一點(diǎn),我們一步步來看,首先畫文字需要準(zhǔn)備以下東西:
1.取4位數(shù)字碼,這個(gè)好說用Math.random()*10即可
2.畫每個(gè)文字時(shí)的Y坐標(biāo)怎么取值(你得控制著Y坐標(biāo),如果畫view外面去,就尷尬了)
3.每個(gè)文字間得有相應(yīng)的間隔(即畫每個(gè)文字時(shí)的X坐標(biāo))
我一個(gè)一個(gè)實(shí)現(xiàn):
取4位數(shù)字碼:
/** * 產(chǎn)生隨機(jī)數(shù)字 */ public static int[] getCheckNum() { int[] tempCheckNum = new int[Config.TEXT_LENGTH];//TEXT_LENGTH是產(chǎn)生幾位數(shù)字 for (int i = 0; i < Config.TEXT_LENGTH; i++) { tempCheckNum[i] = (int) (Math.random() * 10);//我不說你也明白了吧 } return tempCheckNum;//產(chǎn)生4個(gè)數(shù)放在數(shù)組中返回 }
控制Y坐標(biāo):
/** * 計(jì)算驗(yàn)證碼的繪制y點(diǎn)位置 * @param height 傳入CheckView的高度值 * @return */ public static int getYPos(int height) { int tempPositoin = (int) (Math.random() * height); //不能讓它畫的太靠上,如果Y坐標(biāo)<Config.TEXT_SIZE的時(shí)候,畫出的字就會(huì)被遮蓋 if (tempPositoin < Config.TEXT_SIZE) { tempPositoin += Config.TEXT_SIZE; }else if (tempPositoin > (height-Config.TEXT_SIZE)) {//當(dāng)然也不能畫的太靠下 tempPositoin -= Config.TEXT_SIZE; } return tempPositoin; }
控制每個(gè)文字時(shí)的X坐標(biāo)
看上圖,我們把View平分成5分,那么第一個(gè)字的X坐標(biāo)是:getWidth()/5;第二個(gè)字的X坐標(biāo)是getWidth()/5+getWidth()/5;以此類推,這樣是不是這4個(gè)字就平分在這個(gè)View中?好了,好了開始寫代碼,如下:
private void drawNum(Canvas canvas){ int dx = getWidth() / 5; for (int i = 0; i < 4; i++) {//繪制驗(yàn)證控件上的文本 canvas.drawText("" + checkNum[i], dx, getPositon(getHeight()), mPaint); dx += getWidth() / 5; } }
我們來講解一下canvas.drawText()方法的基本用法:
drawText(String text, float x, floaty, Paint paint)
參數(shù)一:String類型的文本,
參數(shù)二:x坐標(biāo),
參數(shù)三:y坐標(biāo),
參數(shù)四:Paint對(duì)象。
3.點(diǎn)擊刷新問題
恭喜大家看到這里,我們還剩下最后一個(gè)問題了,如何點(diǎn)擊刷新UI?簡(jiǎn)單,在onclick()方法中重新刷新驗(yàn)證碼和UI即可,代碼如下:
@Override public void onClick(View v) { checkNum = CheckUtil.getCheckNum();//checkNum付初值 //在這里面更新,重新?lián)Q一套驗(yàn)證碼字符 invalidate(); }
4.最后封魔
好了講到這里,我們接近尾聲了,這個(gè)代碼看起來非常亂,所以,我們需要寫一個(gè)工具類,將以下這幾個(gè)方法用工具類CheckView封裝起來大工告成:
public int[] getCheckNum(); public int[] getLinePos(int height, int width) ; public int[] getCirclePoint(int height, int width); public int getPositon(int height);
以上所述是小編給大家介紹的Android拆輪子系列之寫驗(yàn)證碼控件的方法,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android賬號(hào)注冊(cè)實(shí)現(xiàn)點(diǎn)擊獲取驗(yàn)證碼倒計(jì)時(shí)效果
- Android開發(fā)工程中集成mob短信驗(yàn)證碼功能的方法
- Android獲取和讀取短信驗(yàn)證碼的實(shí)現(xiàn)方法
- Android實(shí)現(xiàn)自動(dòng)提取短信驗(yàn)證碼功能
- Android開發(fā)之獲取短信驗(yàn)證碼后按鈕背景變化并且出現(xiàn)倒計(jì)時(shí)
- Android實(shí)現(xiàn)短信驗(yàn)證碼自動(dòng)填寫功能
- Android如何通過手機(jī)獲取驗(yàn)證碼來完成注冊(cè)功能
相關(guān)文章
Android使用Fragment實(shí)現(xiàn)兼容手機(jī)和平板的程序
這篇文章主要介紹了Android使用Fragment實(shí)現(xiàn)兼容手機(jī)和平板的程序,幫助大家更好的理解和學(xué)習(xí)使用Android開發(fā),感興趣的朋友可以了解下2021-04-04Android 驗(yàn)證碼功能實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 驗(yàn)證碼功能實(shí)現(xiàn)代碼的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08Android?TextView的maxEms和maxLength屬性區(qū)別
這篇文章主要為大家介紹了Android?TextView的maxEms和maxLength屬性區(qū)別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Android 中從屏幕左下角彈出Dialog動(dòng)畫效果的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 中從屏幕左下角彈出Dialog動(dòng)畫效果的實(shí)現(xiàn)代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12flutter PositionedTransition實(shí)現(xiàn)縮放動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了flutter PositionedTransition實(shí)現(xiàn)縮放動(dòng)畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07Android基礎(chǔ)知識(shí)之broadcast廣播詳解
這篇文章主要為大家詳細(xì)介紹了Android基礎(chǔ)知識(shí)之broadcast廣播的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-06-06Android編程使用Intent傳遞對(duì)象的方法分析
這篇文章主要介紹了Android編程使用Intent傳遞對(duì)象的方法,結(jié)合實(shí)例形式詳細(xì)分析了Android使用Intent實(shí)現(xiàn)傳遞對(duì)象的相關(guān)技巧與注意事項(xiàng),需要的朋友可以參考下2016-01-01Android編程簡(jiǎn)單實(shí)現(xiàn)ImageView點(diǎn)擊時(shí)背景圖修改的方法
這篇文章主要介紹了Android編程簡(jiǎn)單實(shí)現(xiàn)ImageView點(diǎn)擊時(shí)背景圖修改的方法,涉及Android針對(duì)背景圖相關(guān)屬性設(shè)置的操作技巧,需要的朋友可以參考下2015-12-12android實(shí)現(xiàn)手機(jī)傳感器調(diào)用
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)手機(jī)傳感器調(diào)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04