最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

android實現(xiàn)圖片驗證碼方法解析(自繪控件)

 更新時間:2017年01月05日 15:47:07   作者:S丶black  
本文主要介紹了android自繪控件的應用--實現(xiàn)圖片驗證碼方法案例,具有一定的參考價值,下面跟著小編一起來看下吧

自繪控件的內容都是自己繪制出來的 大致流程如下:

1.定義一個類繼承view

  1.使用TypedArray初始化屬性集合
    在view的構造方法中 有一個AttributeSet的參數(shù) 很明顯是用來保存控件屬性信息的 我們也的確可以通過循環(huán)然后用鍵值對的方式獲取信息 而TypedArray是用來簡化我們的工作的

  2.重寫onMeasure 測量控件大小

  3.重寫onDraw 繪制控件

2.根據(jù)需求在attrs文件中自定義屬性

declare-styleable 聲明自定義屬性可以自定義一個新屬性也可以引用已經(jīng)存在的屬性兩者的區(qū)別就是新屬性需要添加format進行類型的定義

3.在activity的布局文件使用

自定義圖片驗證碼 演示效果

示例代碼

 <declare-styleable name="VerifyCode">
 <attr name="codeTextSize" format="dimension"/>
 <attr name="codeBackground" format="color"/>
 <attr name="codeLength" format="integer"/>
 <attr name="isContainChar" format="boolean"/>
 <attr name="pointNum" format="integer"/>
 <attr name="linNum" format="integer"/>
 </declare-styleable>
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import java.util.Random;
/**
 * 類描述:自定義驗證碼
 * 創(chuàng)建者:lb
 */
public class VerifyCode extends View {
 private String mCodeText;//文本內容
 private int mCodeTextSize;//文本大小
 private int mCodeLength;//驗證碼長度
 private int mCodeBackground;//背景色
 private boolean isContainChar;//驗證碼是否包含字母
 private int mPointNum;//干擾點數(shù)
 private int mLineNum;//干擾線數(shù)
 private Paint mPaint;//畫筆
 private Rect mBound;//繪制范圍
 private Bitmap bitmap;//驗證碼圖片
 private static Random mRandom = new Random();
 private static int mWidth;//控件的寬度
 private static int mHeight;//控件的高度
 public VerifyCode(Context context) {
 super(context);
 }
 public VerifyCode(Context context, AttributeSet attrs) {
 super(context, attrs);
 initAttrValues(context,attrs);
 initData();
 }
 /**
 * 初始化屬性集合
 * @param context
 * @param attrs
 */
 private void initAttrValues(Context context, AttributeSet attrs){
 // //獲取在AttributeSet中定義的 VerifyCode 中聲明的屬性的集合
 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VerifyCode);
 //獲取TypeArray的長度
 int count=typedArray.getIndexCount();
 for (int i=0;i<count;i++){
  //獲取此項屬性的ID
  int index=typedArray.getIndex(i);
  switch (index){
  case R.styleable.VerifyCode_codeTextSize:
   // 默認設置為16sp,TypeValue類 px轉sp 一個轉換類
   mCodeTextSize =typedArray.getDimensionPixelSize(index,(int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
   break;
  case R.styleable.VerifyCode_codeBackground:
mCodeBackground=typedArray.getColor(index,Color.WHITE);
   break;
  case R.styleable.VerifyCode_codeLength:
   mCodeLength=typedArray.getInteger(index,4);
   break;
  case R.styleable.VerifyCode_isContainChar:
   isContainChar=typedArray.getBoolean(index,false);
   break;
  case R.styleable.VerifyCode_pointNum:
   mPointNum=typedArray.getInteger(index,100);
   break;
  case R.styleable.VerifyCode_linNum:
   mLineNum=typedArray.getInteger(index,3);
   break;
  }
 }
 //Recycles the TypedArray, to be re-used by a later caller
 //官方解釋:回收TypedArray 以便后面的使用者重用
 typedArray.recycle();
 }
 /**
 * 初始化數(shù)據(jù)
 */
 private void initData(){
 mCodeText=getValidationCode(mCodeLength,isContainChar);
 mPaint=new Paint();
 mPaint.setAntiAlias(true);
 mBound=new Rect();
 //計算文字所在矩形,可以得到寬高
 mPaint.getTextBounds(mCodeText,0, mCodeText.length(),mBound);
 }
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 //獲取控件寬高的顯示模式
 int widthMode=MeasureSpec.getMode(widthMeasureSpec);
 int heightMode=MeasureSpec.getMode(heightMeasureSpec);
 //獲取寬高的尺寸值 固定值的寬度
 int widthSize=MeasureSpec.getSize(widthMeasureSpec);
 int heightSize=MeasureSpec.getSize(heightMeasureSpec);
 //設置寬高默認為建議的最小寬高
 int width= getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec) ;
 int height=getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);

// MeasureSpec父布局傳遞給后代的布局要求 包含 確定大小和三種模式
// EXACTLY:一般是設置了明確的值或者是MATCH_PARENT
// AT_MOST:表示子布局限制在一個最大值內,一般為WARP_CONTENT
// UNSPECIFIED:表示子布局想要多大就多大,很少使用
 if (widthMode==MeasureSpec.EXACTLY){
  width=widthSize;
 }else{
  mPaint.setTextSize(mCodeTextSize);
  mPaint.getTextBounds(mCodeText,0,mCodeText.length(),mBound);
  float textWidth=mBound.width();
  int tempWidth=(int)(getPaddingLeft()+textWidth+getPaddingRight());
  width=tempWidth;
 }
 if (heightMode == MeasureSpec.EXACTLY)
 {
  height = heightSize;
 } else
 {
  mPaint.setTextSize(mCodeTextSize);
  mPaint.getTextBounds(mCodeText, 0, mCodeText.length(), mBound);
  float textHeight = mBound.height();
  int tempHeight = (int) (getPaddingTop() + textHeight + getPaddingBottom());
  height = tempHeight;
 }
 //設置測量的寬高
 setMeasuredDimension(width,height);
 }
 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 mWidth=getWidth();
 mHeight=getHeight();

 if (bitmap==null){
  bitmap=createBitmapValidate();
 }
 canvas.drawBitmap(bitmap,0,0,mPaint);
 }
 @Override
 public boolean onTouchEvent(MotionEvent event) {
 switch (event.getAction()){
  case MotionEvent.ACTION_DOWN:
  refresh();
  break;
 }
 return super.onTouchEvent(event);
 }
 /**
 * 創(chuàng)建圖片驗證碼
 * @return
 */
 private Bitmap createBitmapValidate(){
 if(bitmap != null && !bitmap.isRecycled()){
  //回收并且置為null
  bitmap.recycle();
  bitmap = null;
 }
 //創(chuàng)建圖片
 Bitmap sourceBitmap=Bitmap.createBitmap(mWidth,mHeight, Bitmap.Config.ARGB_8888);
 //創(chuàng)建畫布
 Canvas canvas=new Canvas(sourceBitmap);
 //畫上背景顏色
 canvas.drawColor(mCodeBackground);
 //初始化文字畫筆
 mPaint.setStrokeWidth(3f);
 mPaint.setTextSize(mCodeTextSize);
 //測量驗證碼字符串顯示的寬度值
 float textWidth=mPaint.measureText(mCodeText);
 //畫上驗證碼
 int length = mCodeText.length();
 //計算一個字符的所占位置
 float charLength = textWidth / length;
 for (int i = 1; i <= length; i++) {
  int offsetDegree = mRandom.nextInt(15);
  //這里只會產(chǎn)生0和1,如果是1那么正旋轉正角度,否則旋轉負角度
  offsetDegree = mRandom.nextInt(2) == 1 ? offsetDegree : -offsetDegree;
  //用來保存Canvas的狀態(tài)。save之后,可以調用Canvas的平移、放縮、旋轉、錯切、裁剪等操作。
  canvas.save();
  //設置旋轉
  canvas.rotate(offsetDegree, mWidth / 2, mHeight / 2);
  //給畫筆設置隨機顏色
  mPaint.setARGB(255, mRandom.nextInt(200) + 20, mRandom.nextInt(200) + 20,
   mRandom.nextInt(200) + 20);
  //設置字體的繪制位置
  canvas.drawText(String.valueOf(mCodeText.charAt(i - 1)), (i - 1) * charLength+5,
   mHeight * 4 / 5f, mPaint);
  //用來恢復Canvas之前保存的狀態(tài)。防止save后對Canvas執(zhí)行的操作對后續(xù)的繪制有影響。
  canvas.restore();
 }
 //重新設置畫筆
 mPaint.setARGB(255, mRandom.nextInt(200) + 20, mRandom.nextInt(200) + 20,
  mRandom.nextInt(200) + 20);
 mPaint.setStrokeWidth(1);
 //產(chǎn)生干擾效果1 -- 干擾點
 for (int i = 0; i < mPointNum; i++) {
  drawPoint(canvas, mPaint);
 }
 //生成干擾效果2 -- 干擾線
 for (int i = 0; i < mLineNum; i++) {
  drawLine(canvas, mPaint);
 }
 return sourceBitmap;
 }
 /**
 * 生成干擾點
 */
 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);
 }
 /**
 * 獲取驗證碼
 *
 * @param length 生成隨機數(shù)的長度
 * @param contains 是否包含字符串
 * @return
 */
 public String getValidationCode(int length,boolean contains) {
 String val = "";
 Random random = new Random();
 for (int i = 0; i < length; i++) {
  if (contains){
  //字母或數(shù)字
  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));
  }
  }else{
  val += String.valueOf(random.nextInt(10));
  }
 }
 return val;
 }
 /**
 *判斷驗證碼是否一致 忽略大小寫
 */
 public Boolean isEqualsIgnoreCase(String CodeString) {
 return mCodeText.equalsIgnoreCase(CodeString);
 }
 /**
 * 判斷驗證碼是否一致 不忽略大小寫
 */
 public Boolean isEquals(String CodeString) {
 return mCodeText.equals(CodeString);
 }
 /**
 * 提供外部調用的刷新方法
 */
 public void refresh(){
 mCodeText= getValidationCode(mCodeLength,isContainChar);
 bitmap = createBitmapValidate();
 invalidate();
 }
}

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!

相關文章

  • Android控件RadioButton實現(xiàn)多選一功能

    Android控件RadioButton實現(xiàn)多選一功能

    這篇文章主要為大家詳細介紹了Android控件RadioButton實現(xiàn)多選一功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Android自定義view實現(xiàn)圓形waveview

    Android自定義view實現(xiàn)圓形waveview

    這篇文章主要為大家詳細介紹了Android自定義view實現(xiàn)圓形waveview,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • Android 防止多次重復點擊的三種方法的示例

    Android 防止多次重復點擊的三種方法的示例

    本篇文章主要介紹了Android 防止多次重復點擊的三種方法的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Android自定義view制作抽獎轉盤

    Android自定義view制作抽獎轉盤

    這篇文章主要為大家詳細介紹了Android自定義view制作抽獎轉盤,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • Android模擬器實現(xiàn)手機添加文件到sd卡的方法

    Android模擬器實現(xiàn)手機添加文件到sd卡的方法

    這篇文章主要介紹了Android模擬器實現(xiàn)手機添加文件到sd卡的方法,詳細分析了Android模擬器添加文件到sd卡的步驟與相關技巧,需要的朋友可以參考下
    2016-06-06
  • Android 封裝Okhttp+Retrofit+RxJava,外加攔截器實例

    Android 封裝Okhttp+Retrofit+RxJava,外加攔截器實例

    下面小編就為大家分享一篇Android封裝Okhttp+Retrofit+RxJava,外加攔截器實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Flutter實現(xiàn)視頻壓縮功能的示例代碼

    Flutter實現(xiàn)視頻壓縮功能的示例代碼

    移動應用程序中,視頻占用了大量的存儲空間和帶寬,這在一定程度上影響了應用程序的性能和用戶體驗,所以本文為大家準備了Flutter實現(xiàn)視頻壓縮的方法,需要的可以參考一下
    2023-06-06
  • Android給TextView添加點擊事件的實現(xiàn)方法

    Android給TextView添加點擊事件的實現(xiàn)方法

    下面小編就為大家?guī)硪黄狝ndroid給TextView添加點擊事件的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • Android自定義雙向滑動控件

    Android自定義雙向滑動控件

    這篇文章主要為大家詳細介紹了Android自定義雙向滑動控件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 基于Android在布局中動態(tài)添加view的兩種方法(總結)

    基于Android在布局中動態(tài)添加view的兩種方法(總結)

    下面小編就為大家?guī)硪黄贏ndroid在布局中動態(tài)添加view的兩種方法(總結)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10

最新評論

大方县| 井冈山市| 兴义市| 五华县| 甘泉县| 托里县| 奉化市| 镇赉县| 望奎县| 正蓝旗| 青河县| 开江县| 资中县| 上高县| 沅江市| 沂源县| 大石桥市| 交城县| 鄂伦春自治旗| 安福县| 乌海市| 三穗县| 克拉玛依市| 玉屏| 宣威市| 嵊泗县| 通化县| 永寿县| 莆田市| 平遥县| 修水县| 琼结县| 北安市| 自治县| 青川县| 高台县| 连江县| 东明县| 临西县| 多伦县| 佳木斯市|