原理很简单,首先封装一个类,里面是绘制的图形验证码的一些信息,比如,验证码字符串,验证码长度,干扰线等等,这个网上有很多,我也是参考某个的的封装类写的,下面先上效果图:
代码如下:
- package com.imageverification;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import java.util.Random;
- /**
- * Created by Administrator on 2018/5/14/014.
- */
- public class CodeUtil {
- private static final char[] CHARS = {
- '0','1','2','3','4','5','6','7','8','9',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- };
- private static CodeUtil mCodeUtil;
- private int paddingLeft,paddingTop;
- private StringBuilder stringBuilder=new StringBuilder();
- private Random random=new Random();
- private static final int DEFAULT_CODE_LENGTH=4;//验证码长度
- private static final int DEFAULT_FONT_SIZE =60;//验证码字体大小
- private static final int DEFAULT_LINE_NUMBER =3;//干扰线
- private static final int BASE_PADDING_LEFT = 40; //左边距
- private static final int RANGE_PADDING_LEFT = 30;//左边距范围值
- private static final int BASE_PADDING_TOP = 70;//上边距
- private static final int RANGE_PADDING_TOP = 15;//上边距范围值
- private static final int DEFAULT_WIDTH = 300;//默认宽度.图片的总宽
- private static final int DEFAULT_HEIGHT = 100;//默认高度.图片的总高
- private static final int DEFAULT_COLOR = 0xDF;//默认背景颜色值
- private String code;
- public static CodeUtil getInstence(){
- if (mCodeUtil == null){
- mCodeUtil=new CodeUtil();
- }
- return mCodeUtil;
- }
- //生成bitmap形式的验证码图片可通过image.setBitmap();获取展示图片
- public Bitmap createBitmap(){
- paddingLeft=0;
- paddingTop=0;
- Bitmap bitmap= Bitmap.createBitmap(DEFAULT_WIDTH,DEFAULT_HEIGHT,Bitmap.Config.ARGB_8888);
- Canvas canvas=new Canvas(bitmap);
- code=createCode();
- canvas.drawColor(Color.rgb(DEFAULT_COLOR,DEFAULT_COLOR,DEFAULT_COLOR));
- Paint paint=new Paint();
- paint.setTextSize(DEFAULT_FONT_SIZE);
- //验证码
- for (int i = 0; i <code.length() ; i++) {
- randomTextStyle(paint);
- randomPadding();
- canvas.drawText(String.valueOf(code.charAt(i)),paddingLeft,paddingTop,paint);
- }
- //干扰线
- for (int j = 0; j <DEFAULT_LINE_NUMBER ; j++) {
- drawLine(canvas,paint);
- }
- canvas.save();
- canvas.restore();
- return bitmap;
- }
- /**
- * 得到图片验证码字符串信息
- */
- public String getCode(){
- return code;
- }
- //生成干扰线
- private void drawLine(Canvas canvas, Paint paint) {
- int color =randomColor();
- int startX = random.nextInt(DEFAULT_WIDTH);
- int startY = random.nextInt(DEFAULT_HEIGHT);
- int stopX = random.nextInt(DEFAULT_WIDTH);
- int stopY = random.nextInt(DEFAULT_HEIGHT);
- paint.setStrokeWidth(1);
- paint.setColor(color);
- canvas.drawLine(startX, startY, stopX, stopY, paint);
- }
- //随机颜色
- private int randomColor() {
- stringBuilder.delete(0, stringBuilder.length()); //使用之前首先清空内容
- String haxString;
- for (int i = 0; i < 3; i++) {
- haxString = Integer.toHexString(random.nextInt(0xFF));
- if (haxString.length() == 1) {
- haxString = "0" + haxString;
- }
- stringBuilder.append(haxString);
- }
- return Color.parseColor("#" + stringBuilder.toString());
- }
- //随机间距
- private void randomPadding() {
- paddingLeft += BASE_PADDING_LEFT + random.nextInt(RANGE_PADDING_LEFT);
- paddingTop = BASE_PADDING_TOP + random.nextInt(RANGE_PADDING_TOP);
- }
- //随机文本样式
- private void randomTextStyle(Paint paint) {
- int color = randomColor();
- paint.setColor(color);
- paint.setFakeBoldText(random.nextBoolean()); //true为粗体,false为非粗体
- float skewX = random.nextInt(11) / 10;
- skewX = random.nextBoolean() ? skewX : -skewX;
- paint.setTextSkewX(skewX); //float类型参数,负数表示右斜,整数左斜
- // paint.setUnderlineText(true); //true为下划线,false为非下划线
- // paint.setStrikeThruText(true); //true为删除线,false为非删除线
- }
- //生成验证码
- private String createCode() {
- stringBuilder.delete(0,stringBuilder.length());
- for (int i = 0; i <DEFAULT_CODE_LENGTH ; i++) {
- stringBuilder.append(CHARS[random.nextInt(CHARS
- .length)]);
- }
- return stringBuilder.toString();
- }
- }
activity侧:
- package com.imageverification;
- import android.support.v7.app.AppCompatActivity;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ImageButton;
- import android.widget.ImageView;
- import android.widget.TextView;
- import android.widget.Toast;
- /**
- * 图形验证码小demo
- */
- public class MainActivity extends AppCompatActivity implements View.OnClickListener{
- private EditText editText;
- private ImageView imageView;
- private Button button;
- private String finalCode;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initView();
- }
- private void initView() {
- editText=findViewById(R.id.ed);
- imageView=findViewById(R.id.img);
- button=findViewById(R.id.btn);
- imageView.setImageBitmap(CodeUtil.getInstence().createBitmap());
- finalCode=CodeUtil.getInstence().getCode();
- button.setOnClickListener(this);
- imageView.setOnClickListener(this);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()){
- case R.id.btn:
- String message=editText.getText().toString();
- if (message.equalsIgnoreCase(finalCode)){
- Toast.makeText(MainActivity.this,"验证码输入成功",Toast.LENGTH_SHORT).show();
- }else {
- Toast.makeText(MainActivity.this,"验证码输入失败",Toast.LENGTH_SHORT).show();
- }
- break;
- case R.id.img:
- imageView.setImageBitmap(CodeUtil.getInstence().createBitmap());
- finalCode=CodeUtil.getInstence().getCode();
- break;
- }
- }
- }
布局没有什么东西就不贴了。
注:在此说明刚刚说明,(给我自己看的):由于自己疏忽把代码改了一种写法,为了减少代码量,我直接在类的上面去实现了点击事件,刚开始是两个都设置了setOnClickListener事件,然后只给button设置了上下文,imageView忘记了,在点击的时候随机码切换不了。
完整代码:https://download.youkuaiyun.com/download/qq_36636969/10414614