Android生成简单的图片验证码

暑假的班级项目登录界面用到了验证码,就想着简单点弄个图片验证码好了。看了几篇文章还是有点儿懵。然后耐着性子把一篇关于验证码的文章分析了一下。果然还是得有耐心才行啊。 ╰( ̄ω ̄o)  

虽然大致是做出来了,但是还有个小bug,就是文字会出界的问题,如果有更好的解决方案的,欢迎提出呀!(~o ̄3 ̄)

大概是参照这篇博客的:https://blog.csdn.net/wk843620202/article/details/50960904

先上效果图

然后,我们先从布局文件开始

因为主要是看验证码,布局部分我就只截取那一行的代码了

<LinearLayout
          android:layout_width="wrap_content"
          android:layout_height="45dp"
          android:layout_marginTop="10dp"
          android:layout_marginLeft="20dp"
          android:layout_gravity="center_horizontal">
          <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
              android:layout_gravity="left">

              <EditText
                  android:id="@+id/identifyingcode_edittext"
                  android:layout_width="100dp"
                  android:layout_height="match_parent"
                  android:hint="验证码"
                  android:maxLength="4"
                  android:textColor="#4e4e4e"
                  android:textSize="20sp" />
          </LinearLayout>
           <!--这里预留一个ImageView来放图形验证码-->
          <ImageView
              android:id="@+id/identifyingcode_image"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="right"
              />
      </LinearLayout>

     接下来就是一个专门产生图形验证码的类了。首先我们新建一个类(在这里我取名IdentifyingCode)

package util;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

import java.util.Random;

/**
 * @author jiaru
 * 这个类用来生成验证码
 */
public class IdentifyingCode {
    //随机数数组,验证码上的数字和字母
    private static final char[] CHARS={
            '0','1','2', '3', '4', '5', '6', '7', '8', '9',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', '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 IdentifyingCode IdentifyingCode;

    public static IdentifyingCode getInstance(){
        if(IdentifyingCode==null){
            IdentifyingCode=new IdentifyingCode();
        }
        return IdentifyingCode;
    }
    //验证码个数
    private static final int CODE_LENGTH = 4;
    //字体大小
    private static final int FONT_SIZE = 50;
    //线条数
    private static final int LINE_NUMBER = 5;
    //padding,其中base的意思是初始值,而range是变化范围。数值根据自己想要的大小来设置
    private static final int BASE_PADDING_LEFT=10,RANGE_PADDING_LEFT=100,BASE_PADDING_TOP=75,RANGE_PADDING_TOP=50;
    //验证码默认宽高
    private static final int DEFAULT_WIDTH=400,DEFAULT_HEIGHT=150;

    //画布的长宽
    private int width=DEFAULT_WIDTH,height=DEFAULT_HEIGHT;

    //字体的随机位置
    private int base_padding_left=BASE_PADDING_LEFT,range_padding_left=RANGE_PADDING_LEFT,
                base_padding_top=BASE_PADDING_TOP,range_padding_top=RANGE_PADDING_TOP;
    //验证码个数,线条数,字体大小
    private int codeLength=CODE_LENGTH,line_number=LINE_NUMBER,font_size=FONT_SIZE;

    private String code;
    private int padding_left,padding_top;
    private Random random=new Random();

    //验证码图片(生成一个用位图)
    public Bitmap createBitmap(){
        padding_left=0;
        padding_top=0;
        //创建指定格式,大小的位图//Config.ARGB_8888是一种色彩的存储方法
        Bitmap bp=Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        Canvas c=new Canvas(bp);

        code =createCode();
        //将画布填充为白色
        c.drawColor(Color.WHITE);
        //新建一个画笔
        Paint paint =new Paint();
        //设置画笔抗锯齿
        paint.setAntiAlias(true);
        paint.setTextSize(font_size);
        //在画布上画上验证码
//        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        for(int i=0;i<code.length();i++){
            randomTextStyle(paint);
            randomPadding();
        //这里的padding_left,padding_top是文字的基线    
            c.drawText(code.charAt(i)+"",padding_left,padding_top,paint);
        }
        //画干扰线
        for(int i = 0;i<line_number;i++){
            drawLine(c,paint);
        }
        //保存一下画布
        c.save();
        c.restore();
        return bp;
    }

    //生成验证码
    private String createCode(){
        StringBuilder sb=new StringBuilder();
        //利用random生成随机下标
        for(int i=0;i<codeLength;i++){
            sb.append(CHARS[random.nextInt(CHARS.length)]);
        }
        return sb.toString();
    }

    //画线
    private void drawLine(Canvas canvas,Paint paint){
        int color=randomColor();
        int startX=random.nextInt(width);
        int startY=random.nextInt(height);
        int stopX=random.nextInt(width);
        int stopY=random.nextInt(height);
        paint.setStrokeWidth(1);
        paint.setColor(color);
        canvas.drawLine(startX,startY,stopX,stopY,paint);
    }
    //随机文字样式,颜色,文字粗细与倾斜度
    private void randomTextStyle(Paint paint){
        int color=randomColor();
        paint.setColor(color);
        paint.setFakeBoldText(random.nextBoolean());//true为粗体,false为非粗体
        double skew =random.nextInt(11)/10;
        //随机ture或者false来生成正数或者负数,来表示文字的倾斜度,负数右倾,正数左倾
        skew=random.nextBoolean()?skew:-skew;
     //   paint.setUnderlineText(true);//下划线
       // paint.setStrikeThruText(true);//删除线
    }
    //生成随机颜色,利用RGB
    private int randomColor(){
        return randomColor(1);
    }
    private int randomColor(int rate){
        int red=random.nextInt(256)/rate;
        int green=random.nextInt(256)/rate;
        int blue = random.nextInt(256)/rate;
        return Color.rgb(red,green,blue);
    }
    //验证码位置随机
    private void randomPadding(){

        padding_left+=base_padding_left+random.nextInt(range_padding_left);
        padding_top=base_padding_top+random.nextInt(range_padding_top);
    }

    public String getCode(){
        return code;
    }
}

大致的内容我都在注释里讲了。这个生成验证码,主要是将一个位图放在ImageView中,然后用画布将验证码以及干扰线画上去,你也可以设置下划线或者删除线。

然后一开始我发现,我点了几次验证码后,验证码图片会出现,没有了文字的情况,考虑到应该是文字出界了。因为Canvas画文字有基线的,因此,我们只要保证验证码的中心坐标,是依次从左到右,而每个字的y坐标不定,就可以做出,文字在上蹿下跳的效果。

因此作为基线的padding_left,是从base_padding_left依次增加的。而每次增加的幅度,由random随机产生。最大幅度由range_padding_left控制。

而padding_top,因为是可以上上下下,但是,注意不能出界。所以不是padding_top+=base_padding_top+幅度,而是=;也就是说,从左到右,不是依次往下降的,而是上蹿下跳的。这样只要控制base_padding_top和range_padding_top就不会出界了。(其实有更准确的方法的,但是我没有深究下去,文末会附上参考博客,有兴趣的同学研究一下咯)

 

好,那么,接下来就是怎么用这个类啦!

其实只需要,在activity中,定义一个ImageView对象,然后绑定布局中的ImageView,就可以调用IdentifyingCode中的方法来创建一个验证码啦。

然后给这个ImageView设一个监听,就可以点击这个验证码就换一次图片啦!

        private ImageView identifyingCode;
        
        //这里是初始化并设置监听,记得要保存对的验证码,用来验证后面用户输入的对不对
        identifyingCode=(ImageView)findViewById(R.id.identifyingcode_image);
        identifyingCode.setOnClickListener(this);
        identifyingCode.setImageBitmap(IdentifyingCode.getInstance().createBitmap());
        realCode=IdentifyingCode.getInstance().getCode().toLowerCase();

然后在OnClick那里,再来这两个语句,就做到可以刷新验证码了。( ̄︶ ̄)↗ 

       identifyingCode.setImageBitmap(IdentifyingCode.getInstance().createBitmap());
       realCode=IdentifyingCode.getInstance().getCode().toLowerCase();

就这样,一个五颜六色的验证码,就完成了。

 

参考博客:

  1. android随机生成验证码https://blog.csdn.net/wk843620202/article/details/50960904
  2. bitMap的介绍以及他与Canvas的关联https://www.cnblogs.com/jenson138/p/4302073.html
  3. Canvas的介绍https://www.cnblogs.com/huolongluo/p/5797766.html
  4. 画笔Paint的介绍以及他与Canvas的联系https://blog.csdn.net/sinat_35762047/article/details/54965298#一paint和canvas
  5. 里面出现到的Config又是什么呢?https://blog.csdn.net/u010885095/article/details/44938875
  6. 在Canvas上画文字,这里有涉及文字出界内容https://blog.csdn.net/osle123/article/details/52756696
  7. 关于Canvas的drawTexthttps://blog.csdn.net/zly921112/article/details/50401976
  • 17
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 中,可以使用以下步骤来实现图片验证码: 1. 创建一个包含随机字符的图片:可以使用 Canvas 对象绘制图片,也可以使用第三方库,如 Google 的 reCAPTCHA Android 库。 2. 在布局文件中显示图片:可以使用 ImageView 控件来显示图片。 3. 生成验证码并验证用户输入:可以使用 EditText 控件来让用户输入验证码,并在提交时验证用户输入是否与生成验证码相同。 以下是一个简单的示例代码,用于生成和显示图片验证码: ``` public class CaptchaActivity extends AppCompatActivity { private ImageView captchaImage; private EditText captchaInput; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_captcha); captchaImage = findViewById(R.id.captcha_image); captchaInput = findViewById(R.id.captcha_input); // 生成随机验证码 String captchaText = generateCaptcha(); // 将验证码显示在图片中 Bitmap captchaBitmap = createCaptchaBitmap(captchaText); captchaImage.setImageBitmap(captchaBitmap); // 在提交时验证用户输入是否正确 Button submitButton = findViewById(R.id.submit_button); submitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String userInput = captchaInput.getText().toString(); if (userInput.equals(captchaText)) { Toast.makeText(getApplicationContext(), "验证码正确", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), "验证码错误", Toast.LENGTH_SHORT).show(); } } }); } private String generateCaptcha() { // 生成一个包含 4 个随机字符的字符串 Random random = new Random(); StringBuilder captchaBuilder = new StringBuilder(); for (int i = 0; i < 4; i++) { char c = (char) (random.nextInt(26) + 'a'); captchaBuilder.append(c); } return captchaBuilder.toString(); } private Bitmap createCaptchaBitmap(String captchaText) { // 创建一个包含验证码图片 Bitmap captchaBitmap = Bitmap.createBitmap(200, 100, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(captchaBitmap); canvas.drawColor(Color.WHITE); Paint paint = new Paint(); paint.setTextSize(50); paint.setColor(Color.BLACK); paint.setTextAlign(Paint.Align.CENTER); float x = captchaBitmap.getWidth() / 2f; float y = captchaBitmap.getHeight() / 2f + paint.getTextSize() / 3f; canvas.drawText(captchaText, x, y, paint); return captchaBitmap; } } ``` 在上面的代码中,首先使用 `generateCaptcha()` 方法生成一个包含 4 个随机小写字母的字符串,然后使用 `createCaptchaBitmap()` 方法将验证码绘制到图片中。最后,在提交按钮的点击事件中,使用 `if (userInput.equals(captchaText))` 语句来验证用户输入是否与生成验证码相同。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值