Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義控件深入學習 Android生成隨機驗證碼

Android自定義控件深入學習 Android生成隨機驗證碼

編輯:關於Android編程

在上一篇的文章中介紹了自定義控件的屬性,詳情見《詳解Android自定義控件屬性TypedArray以及attrs》。那麼在這基礎上實現隨機驗證碼生成,裡面的代碼是自定義控件以及涉及到自定義view繪畫。
1、先看實現的效果圖


看到這個效果圖是不是感覺還可以。那麼就看看源碼吧。
2、attr文件

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
 
 <attr name="titleText" format="string" /> 
 <attr name="titleTextColor" format="color" /> 
 <attr name="titleTextSize" format="dimension" /> 
 
 <declare-styleable name="AuthCodeView"> 
  <attr name="titleText" /> 
  <attr name="titleTextColor" /> 
  <attr name="titleTextSize" /> 
 </declare-styleable> 
 
</resources> 

3、布局layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:tools="http://schemas.android.com/tools" 
 xmlns:authcodeview="http://schemas.android.com/apk/res/com.example.authcodeview" 
 android:id="@+id/LinearLayout1" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:orientation="vertical" > 
 
 <LinearLayout 
  android:layout_width="match_parent" 
  android:layout_height="wrap_content" > 
 
  <com.example.authcodeview.view.AuthCodeView 
   android:id="@+id/AuthCodeView" 
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
   android:padding="10dp" 
   authcodeview:titleText="3712" 
   authcodeview:titleTextColor="#00ffff" 
   authcodeview:titleTextSize="40sp" /> 
 
  <TextView 
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
   android:text="點擊驗證碼,換一張" /> 
 </LinearLayout> 
 
 <LinearLayout 
  android:layout_width="match_parent" 
  android:layout_height="wrap_content" > 
 
  <TextView 
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
   android:text="輸入驗證碼" /> 
 
  <EditText 
   android:id="@+id/editText1" 
   android:layout_width="match_parent" 
   android:layout_height="wrap_content" 
   android:ems="10" 
   android:inputType="number" > 
 
   <requestFocus /> 
  </EditText> 
 </LinearLayout> 
 
 <Button 
  android:id="@+id/button1" 
  android:layout_width="match_parent" 
  android:layout_height="wrap_content" 
  android:text="驗證" /> 
 
</LinearLayout> 

4、自定義AuthCodeView.class
繼承View,重寫了

onMeasure(int widthMeasureSpec, int heightMeasureSpec)

onDraw(Canvas canvas)方法。
看代碼,有詳細注釋了。

package com.example.authcodeview.view; 
 
import java.util.Random; 
 
import com.example.authcodeview.R; 
 
import android.content.Context; 
import android.content.res.TypedArray; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Rect; 
import android.util.AttributeSet; 
import android.util.TypedValue; 
import android.view.View; 
 
public class AuthCodeView extends View 
{ 
 // 點數設置 
 public static final int POINT_NUM = 100; 
 // 線段數設置 
 public static final int LINE_NUM = 2; 
 //文本 
 private String mTitleText; 
 // 文本的顏色 
 private int mTitleTextColor; 
 // 文本的大小 
 private int mTitleTextSize; 
  
 String[] mCheckNum = new String[4]; 
 Random random = new Random(); 
  
 //繪制時控制文本繪制的范圍 
 private Rect mBound; 
 private Paint mPaint; 
 
 public AuthCodeView(Context context, AttributeSet attrs) 
 { 
  this(context, attrs, 0); 
 } 
 
 public AuthCodeView(Context context) 
 { 
  this(context, null); 
 } 
 
 /** 
  * 獲得我自定義的樣式屬性 
  * 
  * @param context 
  * @param attrs 
  * @param defStyle 
  */ 
 public AuthCodeView(Context context, AttributeSet attrs, int defStyle) 
 { 
  super(context, attrs, defStyle); 
  /** 
   * 獲得我們所定義的自定義樣式屬性 
   */ 
  TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.AuthCodeView, defStyle, 0); 
   
  //獲取在attr文件下,名字為AuthCodeView的declare-styleable屬性有幾個 
  int n = a.getIndexCount(); 
  for (int i = 0; i < n; i++) 
  { 
   int attr = a.getIndex(i); 
   switch (attr) 
   { 
   //這個屬性可以不要,因為都是隨機產生 
   case R.styleable.AuthCodeView_titleText: 
    mTitleText = a.getString(attr); 
    break; 
   case R.styleable.AuthCodeView_titleTextColor: 
    // 默認顏色設置為黑色 
    mTitleTextColor = a.getColor(attr, Color.BLACK); 
    break; 
   case R.styleable.AuthCodeView_titleTextSize: 
    // 默認設置為16sp,TypeValue也可以把sp轉化為px 
    mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( 
      TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); 
    break; 
 
   } 
 
  } 
  a.recycle(); 
   
  mTitleText = randomText(); 
 
  /** 
   * 獲得繪制文本的寬和高 
   */ 
  mPaint = new Paint(); 
  mPaint.setTextSize(mTitleTextSize); 
  mBound = new Rect(); 
  mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); 
 
  this.setOnClickListener(new OnClickListener() 
  { 
 
   @Override 
   public void onClick(View v) 
   { 
    mTitleText = randomText(); 
    postInvalidate(); 
   } 
 
  }); 
 
 } 
  
 //隨機產生驗證碼 
 private String randomText() 
 { 
  StringBuffer sbReturn = new StringBuffer(); 
  for (int i = 0; i < 4; i++) { 
   StringBuffer sb = new StringBuffer(); 
   int randomInt = random.nextInt(10); 
   mCheckNum[i] = sb.append(randomInt).toString(); 
   sbReturn.append(randomInt); 
  } 
   
  return sbReturn.toString(); 
 } 
  
 //獲取驗證碼 
 public String getAuthCode() { 
  return mTitleText; 
 } 
 
 //重寫這個方法,設置自定義view控件的大小 
 @Override 
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
 { 
  // super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
 
  int width = 0; 
  int height = 0; 
 
  /** 
   * 設置寬度 
   */ 
  int specMode = MeasureSpec.getMode(widthMeasureSpec); 
  int specSize = MeasureSpec.getSize(widthMeasureSpec); 
  switch (specMode) 
  { 
  case MeasureSpec.EXACTLY:// 明確指定了 
   width = getPaddingLeft() + getPaddingRight() + specSize; 
   break; 
  case MeasureSpec.AT_MOST:// 一般為WARP_CONTENT 
   width = getPaddingLeft() + getPaddingRight() + mBound.width(); 
   break; 
  } 
 
  /** 
   * 設置高度 
   */ 
  specMode = MeasureSpec.getMode(heightMeasureSpec); 
  specSize = MeasureSpec.getSize(heightMeasureSpec); 
  switch (specMode) 
  { 
  case MeasureSpec.EXACTLY:// 明確指定了 
   height = getPaddingTop() + getPaddingBottom() + specSize; 
   break; 
  case MeasureSpec.AT_MOST:// 一般為WARP_CONTENT 
   height = getPaddingTop() + getPaddingBottom() + mBound.height(); 
   break; 
  } 
 
  setMeasuredDimension(width, height); 
 
 } 
 
 @Override 
 protected void onDraw(Canvas canvas) 
 { 
  //畫背景顏色 
  mPaint.setColor(Color.BLUE); 
  canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); 
   
  //劃線 
  mPaint.setColor(mTitleTextColor); 
  int [] line; 
  for(int i = 0; i < LINE_NUM; i ++) 
  { 
   //設置線寬 
   mPaint.setStrokeWidth(5); 
   line = getLine(getMeasuredHeight(), getMeasuredWidth()); 
   canvas.drawLine(line[0], line[1], line[2], line[3], mPaint); 
  } 
   
  // 繪制小圓點 
  int [] point; 
  int randomInt; 
  for(int i = 0; i < POINT_NUM; i ++)  
  { 
   //隨機獲取點的大小 
   randomInt = random.nextInt(5); 
   point = getPoint(getMeasuredHeight(), getMeasuredWidth()); 
   canvas.drawCircle(point[0], point[1], randomInt, mPaint); 
  } 
 
  //繪制驗證控件上的文本 
  int dx = 20; 
  for(int i = 0; i < 4; i ++){ 
   canvas.drawText("" + mCheckNum[i],dx, getHeight() / 2 + getPositon(mBound.height() / 2), mPaint); 
   dx += (getWidth() / 2 - mBound.width() / 2) + i / 5 + 20; 
  } 
//  canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint); 
 } 
  
 //計算驗證碼的繪制y點位置 
 private int getPositon(int height) { 
  int tempPositoin = (int) (Math.random() * height); 
  if (tempPositoin < 20) { 
   tempPositoin += 20; 
  } 
  return tempPositoin; 
 } 
  
 // 隨機產生點的圓心點坐標 
 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; 
 } 
  
 //隨機產生劃線的起始點坐標和結束點坐標 
 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; 
 } 
} 

5、在MainActivity中怎麼使用這個自定義AuthCodeView
package com.example.authcodeview; 
 
import com.example.authcodeview.view.AuthCodeView; 
import android.os.Bundle; 
import android.app.Activity; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.EditText; 
import android.widget.Toast; 
 
public class MainActivity extends Activity implements OnClickListener 
{ 
 
 private AuthCodeView mauthCodeView; 
 @Override 
 protected void onCreate(Bundle savedInstanceState) 
 { 
  super.onCreate(savedInstanceState); 
  setContentView(R.layout.activity_main); 
   
  initUI(); 
 } 
 
 private void initUI() { 
  mauthCodeView = (AuthCodeView)findViewById(R.id.AuthCodeView); 
  findViewById(R.id.button1).setOnClickListener(this); 
 } 
 
 @Override 
 public void onClick(View v) { 
  switch (v.getId()) { 
  case R.id.button1: 
   EditText editText = (EditText)findViewById(R.id.editText1); 
   String codeString = editText.getText().toString().trim(); 
   if (codeString.equals(mauthCodeView.getAuthCode())) { 
    Toast.makeText(this, "驗證碼驗證正確!", Toast.LENGTH_LONG).show(); 
   }else { 
    Toast.makeText(this, "驗證碼錯誤!", Toast.LENGTH_LONG).show(); 
   } 
   break; 
 
  default: 
   break; 
  } 
   
 } 
 
 
} 

源碼下載:Android生成隨機驗證碼Demo

以上就是本文的全部內容,希望對大家的學習有所幫助。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved