Android自定义控件深入学习 Android生成随机验证码

2019/7/7 19:59:35

本文主要是介绍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

以上就是本文的全部内容,希望对大家的学习有所帮助。



这篇关于Android自定义控件深入学习 Android生成随机验证码的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程