当前位置: 移动技术网 > 移动技术>移动开发>Android > Android自定义控件深入学习 Android生成随机验证码

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

2019年07月24日  | 移动技术网移动技术  | 我要评论

在上一篇的文章中介绍了自定义控件的属性,详情见《详解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; 
  } 
   
 } 
 
 
} 

源码下载:

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网