Android自定义控件(特效三) 自定义View实现图片验证码

之前在一些APP上看到图片验证码的效果,百度后发现网上大多数的代码都是写了一个Bitmap工具类来实现的,于是,今天尝试用自定义View来实现该效果

先上图:



先来说说思路,首先画一个大的背景图,然后生成验证码,最后在图中画出随机生成的验证码,以及干扰的线条


先写个View,继承View并实现构造方法、onDraw()

在OnDraw里,先来画一个大的背景图

canvas.drawColor(Color.rgb(219, 204, 133));

接下来,就是生成验证码了,这里我的验证码是由0-9、a-z、A-Z组成的,代码如下:

private static final char[] CODES = { '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', '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' };
StringBuilder buffer = new StringBuilder();
  for (int i = 0; i < 4; i++) {
   buffer.append(CODES[random.nextInt(CODES.length)]);
  }


然后buffer.toString()就是我们随机生成的验证码了。


最后,在onDraw里画出我们的验证码,因为验证码的位置、是否加粗、颜色都需要随机,所以代码如下:

CODE_X += PADDING_X + random.nextInt(RANDOM_MAX_X);// 随机生成验证码X轴的位置
CODE_Y = PADDING_Y + random.nextInt(RANDOM_MAX_Y);// 随机生成验证码Y轴的位置
paint.setColor(randomColor());
paint.setFakeBoldText(random.nextBoolean()); // 随机粗体/非粗体
canvas.drawText(myCode.charAt(i) + "", CODE_X, CODE_Y, paint);

这样,就画出了验证码,然后我们可以再画出干扰的线条

int startX = random.nextInt(WIDTH); // 线条起始X坐标
int startY = random.nextInt(HEIGHT); // 线条起始Y坐标
int stopX = random.nextInt(WIDTH); // 线条结束X坐标
int stopY = random.nextInt(HEIGHT); // 线条结束Y坐标
paint.setStrokeWidth(2);// 设置线条的粗
paint.setColor(randomColor());// 设置线条颜色
canvas.drawLine(startX, startY, stopX, stopY, paint);// 画干扰线条

以上就是主要代码,其实代码都很简单,只要思路明确了,做起来还是很容易的

完整代码:


import java.util.Random;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
 * 自定义验证码
 * 
 * @author 帽檐遮不住阳光
 * @Date 2016/5/11
 * 
 */
public class MyView extends View {

	/**
	 * 验证码长度
	 */
	private final int CODELENGTH = 4;

	/**
	 * 验证码字体大小
	 */
	private final int TEXTZISE = 40;

	/**
	 * 干扰线条的数目
	 */
	private final int LINENUM = 5;

	/**
	 * 验证码X坐标
	 */
	private int CODE_X;

	/**
	 * 验证码Y坐标
	 */
	private int CODE_Y;

	/**
	 * 验证码每个字符X轴之间的间距
	 */
	private final int PADDING_X = 20;

	/**
	 * 验证码每个字符Y轴之间的间距
	 */
	private final int PADDING_Y = 25;

	/**
	 * 每次随机生成验证码时X轴最大值
	 */
	private final int RANDOM_MAX_X = 20;

	/**
	 * 每次随机生成验证码时Y轴最大值
	 */
	private final int RANDOM_MAX_Y = 40;

	/**
	 * 如果State为True,则随机生成验证码 如果State为False,则生成用户输入框输入的验证码
	 */
	private boolean state = true;

	/**
	 * 验证码背景框的宽
	 */
	private final int WIDTH = 160;

	/**
	 * 验证码背景框的高
	 */
	private final int HEIGHT = 100;

	/**
	 * 验证码
	 */
	private String myCode;

	Paint paint;
	private Random random = new Random();
	private static final char[] CODES = { '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', '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' };

	public MyView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		paint = new Paint();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		CODE_X = 0;// 将x轴位置设为0
		paint.setTextSize(TEXTZISE);// 设置字体大小
		canvas.drawColor(Color.rgb(219, 204, 133));// 背景颜色

		if (state) {
			// 如果为True 则随机生成验证码,否则使用用户输入的验证码
			myCode = createCode();
		}

		// 画验证码
		for (int i = 0; i < CODELENGTH; i++) {
			CODE_X += PADDING_X + random.nextInt(RANDOM_MAX_X);// 随机生成验证码X轴的位置
			CODE_Y = PADDING_Y + random.nextInt(RANDOM_MAX_Y);// 随机生成验证码Y轴的位置
			paint.setColor(randomColor());
			paint.setFakeBoldText(random.nextBoolean()); // 随机粗体/非粗体
			canvas.drawText(myCode.charAt(i) + "", CODE_X, CODE_Y, paint);
		}

		// 画干扰线条
		for (int i = 0; i < LINENUM; i++) {
			drawLine(canvas, paint);
		}
	}

	/**
	 * 随机生成验证码
	 * 
	 * @return
	 */
	private String createCode() {
		StringBuilder buffer = new StringBuilder();
		for (int i = 0; i < CODELENGTH; i++) {
			buffer.append(CODES[random.nextInt(CODES.length)]);
		}
		return buffer.toString();
	}

	/***
	 * 画干扰线条
	 * 
	 * @param canvas
	 * @param paint
	 */
	private void drawLine(Canvas canvas, Paint paint) {
		int startX = random.nextInt(WIDTH); // 线条起始X坐标
		int startY = random.nextInt(HEIGHT); // 线条起始Y坐标
		int stopX = random.nextInt(WIDTH); // 线条结束X坐标
		int stopY = random.nextInt(HEIGHT); // 线条结束Y坐标
		paint.setStrokeWidth(2);// 设置线条的粗
		paint.setColor(randomColor());// 设置线条颜色
		canvas.drawLine(startX, startY, stopX, stopY, paint);// 画干扰线条
	}

	/***
	 * 随机生成RGB
	 * 
	 * @return
	 */
	private int randomColor() {
		int red = random.nextInt(256);
		int green = random.nextInt(256);
		int blue = random.nextInt(256);
		return Color.rgb(red, green, blue);
	}

	/**
	 * 刷新验证码
	 */
	public void refresh(boolean userState, String Code) {
		myCode = Code;
		state = userState;
		invalidate();
	}

	public String getCode() {
		return myCode;
	}

}

Demo:    http://download.csdn.net/detail/qq_18612815/9516939





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值