自定义控件之_验证码

来源:互联网 发布:php cookie存储目录 编辑:程序博客网 时间:2024/06/05 07:37
    现在有个需求,就是写一个可是动态生成验证码的自定义控件,然后我们就开始一个简单的自定义控件---验证码。
    首先,我们需要考虑的问题是这个自定义控件的功能,当然,我只写了一点点功能,我的想法是提供一种随机产生数字或者字母组合的字符串,用户输入这个字符串就能验证成功,第二种就是随机生成一个十位数之内的加减乘的算式,用户计算出改算式的结果,输入进行验证即可。
    对于第一种方式,我们要考虑的问题是怎么随机生成数字加上字母的混合字符串,现在我说下我的思路:
public String getTexts(int index) {
Random ran = new Random();
if (index % 2 == 0) {
return String.valueOf(ran.nextInt(10));
} else {
return String.valueOf((char) (ran.nextInt(26) + 65));
}
}
        在上面这段代码中,我们通过一个int类型的值的奇偶性来判断输出的是字母还是数字,如果是偶数,就随机生成一个10以内的数字,否则,生成一个65-91的数字,转成字母,当然这里是大写的,小写的也可以自己稍微处理一下。
/**
* 该方法是用来生成随机数样式的验证码
*
* @param canvas
*/
private void randomDraw(Canvas canvas) {
String str = "";
Random random = new Random();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setTextSize(40);
for (int i = 0; i < 5; i++) {
paint.setColor(colors[random.nextInt(colors.length)]);
String s = getTexts(random.nextInt(100));
int angle = random.nextInt(90);
canvas.rotate(angle, width * i + width / 2, height);
canvas.drawText(s, width * i + width / 2, height, paint);
canvas.rotate(-angle, width * i + width / 2, height);
str += s;
}
captchaListener.onClick(str);
}
    在上面的代码中,我们通过给画笔设置 不同的颜色,设置不同的倾斜角度来达到生成歪七扭八的验证码的效果,最后返回生成的字符串,提供给最后验证验证码的方法使用。
    下面来说说生成算式的方法:
    在下面的代码中,注释掉了对文字歪七扭八的处理,因为对于运算符来的加号说,歪了就有可能被认为乘法。
    我们首先随机生成好第一个和第二个数,初始化好运算符,计算出结果,接下来就是将生成好的东西画在画布上就好了。
/**
* 该方法是用来生成计算式样式的验证码
*
* @param canvas
*/
private void calculatorDraw(Canvas canvas) {
String[] strs = new String[4];
Random random = new Random();
firstNum = random.nextInt(11);
strs[0] = String.valueOf(firstNum);
secondNum = random.nextInt(11);
strs[2] = String.valueOf(secondNum);
//记录下运算符的下标
int index = random.nextInt(3);
strs[1] = type[index];
strs[3] = "=";
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setTextSize(40);
for (int i = 0; i < 4; i++) {
paint.setColor(colors[random.nextInt(colors.length)]);
// int angle = random.nextInt(90);
// canvas.rotate(angle, width * i + width / 2, height);
canvas.drawText(strs[i], width * i + width / 2, height, paint);
// canvas.rotate(-angle, width * i + width / 2, height);
}
//计算结果
switch (index) {
case 0:
result = firstNum + secondNum;
break;
case 1:
result = firstNum - secondNum;
break;
case 2:
result = firstNum * secondNum;
break;
}
}
下面是整个自定义View的所有代码:
package com.example.ycdyus.day26.view;
 
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
 
import com.example.ycdyus.day26.R;
 
import java.util.Random;
 
/**
* Created by ycdyus on 2015/9/29.
*/
public class Captcha extends View implements View.OnClickListener {
private Paint paint;
 
private CaptchaListener captchaListener;
 
//定义生成算式的属性
private int firstNum;//记录第一个数
private int secondNum;//记录第二个数
private String[] type = new String[]{"+", "-", "x"};
private int[] colors = new int[]{Color.RED, Color.YELLOW, Color.BLUE, Color.GRAY, Color.GREEN};
private int result;
private int width;
private int height;
private int model=0;
 
public int getModel() {
return model;
}
 
public void setModel(int model) {
this.model = model;
}
 
public Captcha(Context context) {
this(context, null);
}
 
public Captcha(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
 
public Captcha(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
 
private void init(Context context, AttributeSet attrs) {
paint = new Paint();
this.setOnClickListener(this);
}
 
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
width = getWidth() / 5;
height = getHeight() / 2;
//给画布画一个背景
Rect rect = new Rect(0, 0, getWidth(), getHeight());
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.back), rect, rect, paint);
//
if(model==0){
calculatorDraw(canvas);
}else{
randomDraw(canvas);
}
}
 
/**
* 该方法是用来生成计算式样式的验证码
*
* @param canvas
*/
private void calculatorDraw(Canvas canvas) {
String[] strs = new String[4];
Random random = new Random();
firstNum = random.nextInt(11);
strs[0] = String.valueOf(firstNum);
secondNum = random.nextInt(11);
strs[2] = String.valueOf(secondNum);
//记录下运算符的下标
int index = random.nextInt(3);
strs[1] = type[index];
strs[3] = "=";
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setTextSize(40);
for (int i = 0; i < 4; i++) {
paint.setColor(colors[random.nextInt(colors.length)]);
// int angle = random.nextInt(90);
// canvas.rotate(angle, width * i + width / 2, height);
canvas.drawText(strs[i], width * i + width / 2, height, paint);
// canvas.rotate(-angle, width * i + width / 2, height);
}
//计算结果
switch (index) {
case 0:
result = firstNum + secondNum;
break;
case 1:
result = firstNum - secondNum;
break;
case 2:
result = firstNum * secondNum;
break;
}
captchaListener.onClick(String.valueOf(result));
}
 
/**
* 该方法是用来生成随机数样式的验证码
*
* @param canvas
*/
private void randomDraw(Canvas canvas) {
String str = "";
Random random = new Random();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setTextSize(40);
for (int i = 0; i < 5; i++) {
paint.setColor(colors[random.nextInt(colors.length)]);
String s = getTexts(random.nextInt(100));
int angle = random.nextInt(90);
canvas.rotate(angle, width * i + width / 2, height);
canvas.drawText(s, width * i + width / 2, height, paint);
canvas.rotate(-angle, width * i + width / 2, height);
str += s;
}
captchaListener.onClick(str);
}
 
public String getTexts(int index) {
Random ran = new Random();
if (index % 2 == 0) {
return String.valueOf(ran.nextInt(10));
} else {
return String.valueOf((char) (ran.nextInt(26) + 65));
}
}
 
public CaptchaListener getCaptchaListener() {
return captchaListener;
}
 
public void setCaptchaListener(CaptchaListener captchaListener) {
this.captchaListener = captchaListener;
}
 
@Override
public void onClick(View v) {
invalidate();
 
}
 
public interface CaptchaListener {
void onClick(String result);
}
}
    说完这些,我们要怎么使用呢?通过包名加类名的形式在布局文件中使用就可以了,在Java代码 中,我们先要设置一下模式,也就是使用随机生成字符串还是算式的模式,然后要实现一个对生成结果的监听事件,对生成的结果进行监听,这样就可以在这里使用这些结果来判断是否验证成功。
    MainActivity.java
package com.example.ycdyus.day26;
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
 
import com.example.ycdyus.day26.view.Captcha;
import com.example.ycdyus.day26.view.CircleProgressBar;
 
public class SecndActivity extends AppCompatActivity implements View.OnClickListener {
// private CircleProgressBar circleProgressBar;
private Captcha calcu, random;
private EditText calcuEdittext, randomEdittext;
private Button calcuButton, randomButton;
private String calcuResult;
private String randomResult;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_secnd);
// 算式模式
calcu = (Captcha) findViewById(R.id.id_captche_calculator);
calcu.setModel(0);
calcu.setCaptchaListener(new Captcha.CaptchaListener() {
@Override
public void onClick(String result) {
calcuResult = result;
}
});
//随机数模式
random = (Captcha) findViewById(R.id.id_captche_random);
random.setModel(1);
random.setCaptchaListener(new Captcha.CaptchaListener() {
@Override
public void onClick(String result) {
randomResult = result;
}
});
//实例化控件
init();
// initView();
}
 
private void init() {
calcuEdittext = (EditText) findViewById(R.id.et_calcu_second);
randomEdittext = (EditText) findViewById(R.id.et_random_second);
calcuButton = (Button) findViewById(R.id.btn_calcu_second);
randomButton = (Button) findViewById(R.id.btn_random_second);
calcuButton.setOnClickListener(this);
randomButton.setOnClickListener(this);
}
 
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_calcu_second:
if(calcuEdittext.getText().toString().equals(calcuResult)){
Toast.makeText(this,"验证成功",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this,"验证失败",Toast.LENGTH_SHORT).show();
}
break;
case R.id.btn_random_second:
if(randomEdittext.getText().toString().equals(randomResult)){
Toast.makeText(this,"验证成功",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this,"验证失败",Toast.LENGTH_SHORT).show();
}
break;
}
}
}
    下面是布局文件
    layout_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context="com.example.ycdyus.day26.SecndActivity">
 
<TextView
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:text="算式形式的验证码"
android:layout_marginBottom="10dp"
android:layout_height="wrap_content" />
<com.example.ycdyus.day26.view.Captcha
android:id="@+id/id_captche_calculator"
android:layout_width="150dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal" />
 
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="horizontal">
 
<EditText
android:id="@+id/et_calcu_second"
android:layout_width="100dp"
android:layout_height="wrap_content" />
 
<Button
android:text="点击验证"
android:id="@+id/btn_calcu_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
 
<TextView
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:text="随机数形式的验证码"
android:layout_marginBottom="10dp"
android:layout_height="wrap_content" />
 
<com.example.ycdyus.day26.view.Captcha
android:id="@+id/id_captche_random"
android:layout_width="150dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal" />
 
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="horizontal">
 
<EditText
android:id="@+id/et_random_second"
android:layout_width="100dp"
android:layout_height="wrap_content" />
 
<Button
android:text="点击验证"
android:id="@+id/btn_random_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
 
</LinearLayout>

    这个下面是实现的效果。看客们看看就好,不要吐槽。


1 0