在Android客户端应用开发中,往往需要短信验证码或者随机验证码来限制用户的操作或者认证。短信验证码是为了对用户进行认证,主要通过Http协议等通信协议实现;随机验证码很大程度是为限制或者提示用户相关操作。随机验证码的验证主要有两种方式:请求服务器验证,本地验证。比如,在用户向服务器发送登录请求,我们通过随机验证码(本地验证即可)限制用户随意按请求按钮,演示如下:
源码实战
(1)src/.../createCode.java
功能:使用Random、Canvas、Paint及其相关方法创建包含4个显示风格、位置不同字符的位图。
package com.example.randomcode; import java.util.Random; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; /** * 项目名称/版本号:RandomCode/v1.0 * 包 名:com.example.randomcode * 类描述:(1)生成一组随机数; * (2)设置随机数风格,并绘制canvas.drawText()到位图上 * (3)再在位图上绘制风格变化的干扰线条 * 创建人:jiangdongguo * 创建时间:2015-6-6 下午3:22:41 * 博客地址:http://blog.csdn.net/u012637501 */ public class createCode { private static final char[] CHARS = { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; //预定随机数库 private static final int CodeLength = 4; // 随机数个数 private static final int LineNumber =8; //线条数目 private static final int WIDTH =140, HEIGHT = 80; // 位图长、宽 private static final int FontSize = 40; //随机数字体大小 private static int base_padding_left ; private static final int random_padding_left = 23, base_padding_top = 45, random_padding_top = 10; private static Random random = new Random(); /********************************************************************************* * 方 法 名:createRandomBitmap * 功能描述:生成随机验证码视图 * Data :2015-6-6[J] *********************************************************************************/ public static Bitmap createRandomBitmap(){ /** * (1)生成一组随机数 * */ String code = createRandomText(); //生成4个随机数 /*** * (2)创建位图Bitmap,画布Canvas,初始化画笔Paint * */ Bitmap bitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Config.ARGB_8888); //创建位图,并指定其长、宽 Canvas canvas = new Canvas(bitmap); //创建指定位图的画布 canvas.drawColor(Color.WHITE); //设置画布的背景为白色 Paint paint = new Paint(); //定义画笔paint paint.setTextSize(FontSize); //设置画笔字体大小 /** * (3)生成四个随机数风格各异(颜色、位置、形状)的位图 * */ base_padding_left = 20; for(int i=0;i<code.length();i++){ //设置一个随机数的风格 int color = RandomColor(); paint.setColor(color); //设置(画笔)该随机数的颜色 paint.setFakeBoldText(false);//设置画笔为非粗体 float skewX = random.nextInt(11)/10; skewX = random.nextBoolean() ? skewX :(-skewX); paint.setTextSkewX(skewX); //设置字体倾斜方向(负数表示右斜,整数表示左斜) //设置一个随机数位置 // int padding_left = base_padding_left + random.nextInt(random_padding_left); int padding_top =base_padding_top + random.nextInt(random_padding_top); //绘制该随机数 canvas.drawText(code.charAt(i)+"" ,base_padding_left, padding_top, paint); base_padding_left += random_padding_left; } /** * (4)绘制线条 **/ for(int i=0;i<LineNumber;i++){ mdrawLine(canvas, paint); } canvas.save(Canvas.ALL_SAVE_FLAG); //保存 canvas.restore(); return bitmap; } /********************************************************************************* * 方 法 名:createRandomText * 功能描述: * Data :2015-6-6[J] *********************************************************************************/ private static String createRandomText(){ StringBuilder buffer = new StringBuilder(); for(int i=0;i<CodeLength;i++){ buffer.append(CHARS[random.nextInt(CHARS.length)]); //CHARS下标限定在0~CodeLength之间 } return buffer.toString(); //生成4个随机数 } /******************************************************************************** * 方 法 名:RandomColor * 功能描述:生成一个随机颜色 * Data :2015-6-6[J] *********************************************************************************/ private static int RandomColor(){ int red = random.nextInt(256); //红色:0~256之间 int green = random.nextInt(256); //绿色:0~256之间 int blue = random.nextInt(256); //蓝色:0~256之间 return Color.rgb(red, green, blue); //返回生成随机颜色值 } /********************************************************************************* * 方 法 名:mdrawLine * 功能描述:绘制一条线条,参数:当前画布,当前画笔 * Data :2015-6-6[J] **********************************************************************************/ private static void mdrawLine(Canvas canvas,Paint paint){ //a.设置该线条颜色 int color = RandomColor(); paint.setColor(color); //b.设置该随机数的位置(起点和终点,0~WIDTH,0~HEIGHT) int startX = random.nextInt(WIDTH); int startY = random.nextInt(HEIGHT); int stopX = random.nextInt(WIDTH); int stopY = random.nextInt(HEIGHT); canvas.drawLine(startX, startY, stopX, stopY, paint); } }
注释:创建随机字符位图的关键在于设计每个字符在位图上的显示位置,若每个字符显示的上下、左右边距不合适,字符将在位图上显示不出来。特别要注意每个字符的左右边距,代码如下:
private static int base_padding_left ;
private static final int random_padding_left = 23,
base_padding_top = 45, random_padding_top = 10;
base_padding_left = 20; //第一个字符到位图左边界距离
for(int i=0;i<code.length();i++){
//设置该字符能显示距离位图垂直位置
int padding_top =base_padding_top + random.nextInt(random_padding_top);
canvas.drawText(code.charAt(i)+"" ,base_padding_left, padding_top, paint);
base_padding_left += random_padding_left; //调整该字符与前一个字符的间隔距离
}
(2)src/.../MainActivity.java
功能:将创建好的位图显示到界面布局的ImageButton组件中
package com.example.randomcode; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final ImageButton imageButton = (ImageButton)findViewById(R.id.myImage); imageButton.setImageBitmap(createCode.createRandomBitmap()); imageButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { imageButton.setImageBitmap(createCode.createRandomBitmap()); } }); } }
(3)res/layout/main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageButton android:id="@+id/myImage" android:layout_width="160dp" android:layout_height="80dp" android:layout_centerInParent="true" /> </LinearLayou>
(4)效果演示