Android自定义控件深入学习 Android生成随机验证码
程序员文章站
2024-02-21 18:47:16
在上一篇的文章中介绍了自定义控件的属性,详情见《详解android自定义控件属性typedarray以及attrs》。那么在这基础上实现随机验证码生成,里面的代码是自定义控...
在上一篇的文章中介绍了自定义控件的属性,详情见《详解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
以上就是本文的全部内容,希望对大家的学习有所帮助。