千家信息网

js怎么自定义随机验证码控件

发表于:2024-11-28 作者:千家信息网编辑
千家信息网最后更新 2024年11月28日,本篇内容介绍了"js怎么自定义随机验证码控件"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!随机获取要
千家信息网最后更新 2024年11月28日js怎么自定义随机验证码控件

本篇内容介绍了"js怎么自定义随机验证码控件"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

随机获取要展示的字符串,然后以不规则的形式绘制出来,添加一些干扰因素,例如干扰线、噪点等。

1:首先想到的就是实现一个自定义View,在其onDraw()中绘制,但是此方式会遇到一个比较棘手的问题。

当键盘弹出与收回时,会触发自定义View的onDraw()方法,那样就会重绘一次,造成位置变动。

解决办法:

我能想到的解决办法就是类似于打快照的办法。在每次绘制后就将其现有信息保存起来,使被动触发的onDraw()均使用快照,而只有我们主动刷新时再重新设置绘制信息。

2:不使用自定义View,而是生成一张图片,设置到ImageView中,这样就避免了自定义View的问题。

实现方式

下面是完整的代码,主要关注两个接口方法:

createCodeImage():创建随机验证码图片

getCode() :获取当前验证码

public class RandomVerifyCode {    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 Context mContext;    private ImageView imgContainer;    private int textCount;    private int lineCount;    private float textSize;    private int width = 100, height = 40;    private String code;    private Random random = new Random();    private Paint paint = new Paint();    public RandomVerifyCode(Context context, @NonNull ImageView imgContainer, int textCount, int lineCount, float textSizeDp) {        this.mContext = context;        this.textCount = textCount;        this.lineCount = lineCount;        this.textSize = CommonUtils.dp2px(mContext, textSizeDp);        this.imgContainer = imgContainer;        imgContainer.setOnClickListener(v -> {            createCodeImage();        });        paint.setAntiAlias(true);        paint.setTextSize(textSize);    }    public void createCodeImage() {        code = createCode();        imgContainer.post(() -> {            width = imgContainer.getWidth();            height = imgContainer.getHeight();            Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);            Canvas canvas = new Canvas(bitmap);            int tenDp = CommonUtils.dp2px(mContext, 10);            int dx = tenDp;            for (int i = 0; i < textCount; i++) {                randomTextStyle(paint);                canvas.drawText(code.charAt(i) + "", dx, getDrawY(height, CommonUtils.dp2px(mContext, 3),                        (int) textSize), paint);                dx += (width - tenDp * 2) / textCount;            }            for (int i = 0; i < lineCount; i++) {                drawLine(canvas, paint);            }            canvas.save();            canvas.restore();            imgContainer.setImageBitmap(bitmap);        });    }    public String getCode() {        if (TextUtils.isEmpty(code))            throw  new UnsupportedOperationException("请先调用createCodeImage()方法");        return code;    }    //随机生成文字样式,颜色,粗细,倾斜度    private void randomTextStyle(Paint paint) {        int color = Color.rgb(255, 255, 255);        paint.setColor(color);        paint.setFakeBoldText(random.nextBoolean());  //true为粗体,false为非粗体        float skewX = random.nextFloat();        skewX = random.nextBoolean() ? skewX : -skewX;        paint.setTextSkewX(skewX); //float类型参数,负数表示右斜,正数左斜    }    private void drawLine(Canvas canvas, Paint paint) {        int color = randomColor(1);        int startX = random.nextInt(width);        int startY = random.nextInt(height);        int stopX = random.nextInt(width);        int stopY = random.nextInt(height);        paint.setStrokeWidth(3);        paint.setColor(color);        canvas.drawLine(startX, startY, stopX, stopY, paint);    }    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 String createCode() {        StringBuilder buffer = new StringBuilder();        for (int i = 0; i < textCount; i++) {            buffer.append(CHARS[random.nextInt(CHARS.length)]);        }        return buffer.toString();    }    private int getDrawY(int height, int offsetY, int textHeight) {        double tempY = Math.random() * (height - textHeight - offsetY * 2) + textHeight;        return (int) tempY;    }}

如何使用

在需要展示验证码的地方放一个ImageView控件,设置其背景色,大小等。然后调用相关方法即可,如下所示。

public class MainActivity extends AppCompatActivity {    private RandomVerifyCode verifyCode;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ImageView codeImg = findViewById(R.id.iv_verify_code);        verifyCode = new RandomVerifyCode(this, codeImg, 4, 5, 25);        verifyCode.createCodeImage();    }}

改进

本类有非常多可以改进的地方,有兴趣的同学可以尝试:

验证码的颜色是固定为白色,可以改进为可配置。

现在只有干扰线,可以尝试添加噪点

干扰线宽度不能配置

验证码数据源不能配置,现在为0到9,小写字母与大写字母,如果遇到纯数字或纯字母等需求,需要修改源代码。

如果改了以上几条,最好考虑使用Builder模式重构此类。

"js怎么自定义随机验证码控件"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0