美文网首页
kotlin 随机生成图片验证码

kotlin 随机生成图片验证码

作者: 落叶随风花落入泥 | 来源:发表于2020-04-30 15:39 被阅读0次

    引言

    图片随机验证码,登陆、注册经常用到,最近项目需要使用手机验证码和随机图片验证码两种方式进行注册登陆。从网上找了很多文章,看了一下源码,最后总结如下:

    核心思路

    一、它是一张图片 + 随机数字 + 线条组合而成
    二、通过bitmap 工厂类生成一个bitmap,把bitmap 给canvs 充当画板,在其上进行绘制 文字+斜线
    三、文字是通过随机数从我们的charArry中获取,线也是通过随机数据,设置起点和终点
    四、对外提供获取验证码的接口
    五、可以根据这个随机码做一下逻辑操作

    代码如下:

    import android.graphics.Bitmap
    import android.graphics.Canvas
    import android.graphics.Color
    import android.graphics.Paint
    import com.standard.base.utils.LogUtils
    import java.util.*
    
    
    /**
     *  Create by zsy on 2020/4/30
     *
     *  创建随机图片验证码
     */
    class CreateVCodeUtils private constructor() {
    
    
    companion object {
        private var createVCodeUtils: CreateVCodeUtils? = null
        //default settings
        //验证码默认随机数的个数
        private const val DEFAULT_CODE_LENGTH = 4
        //默认字体大小
        private const val DEFAULT_FONT_SIZE = 25
        //默认线条的条数
        private const val DEFAULT_LINE_NUMBER = 5
        //padding值
        private const val BASE_PADDING_LEFT = 10 //padding值
        private const val RANGE_PADDING_LEFT = 15 //padding值
        private const val BASE_PADDING_TOP = 15 //padding值
        private const val RANGE_PADDING_TOP = 20
    
        //验证码的默认宽高
        private const val DEFAULT_WIDTH = 100  //验证码的默认宽高
        private const val DEFAULT_HEIGHT = 40
    
    
        //随机数数组
        private val CHARS = charArrayOf(
            '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'
        )
    
        fun getInstance(): CreateVCodeUtils {
            if (createVCodeUtils == null) {
                createVCodeUtils = CreateVCodeUtils()
            }
            return createVCodeUtils!!
        }
    
    
    }
    
    //settings decided by the layout xml
    //canvas width and height
    private var width = DEFAULT_WIDTH  //settings decided by the layout xml
    //canvas width and height
    private var height = DEFAULT_HEIGHT
    
    //random word space and pading_top
    private var base_padding_left = BASE_PADDING_LEFT  //random word space and pading_top
    private var range_padding_left = RANGE_PADDING_LEFT
    //random word space and pading_top
    private var base_padding_top = BASE_PADDING_TOP //random word space and pading_top
    private val range_padding_top = RANGE_PADDING_TOP
    
    //number of chars, lines; font size
    private var codeLength = DEFAULT_CODE_LENGTH  //number of chars, lines; font size
    private var line_number = DEFAULT_LINE_NUMBER  //number of chars, lines; font size
    private var font_size = DEFAULT_FONT_SIZE
    
    
    //variables
    private var code: String? = null
    private var padding_left = 0
    private var padding_top: Int = 0
    private var random: Random = Random()
    
    /**
     * 创建图片验证码
     */
    fun createBitmap(): Bitmap {
        padding_left = 0
        padding_top = 0
        val bp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        code = createCode()
        val c = Canvas(bp)
        c.drawColor(Color.WHITE)
        val paint = Paint()
        paint.setAntiAlias(true);
        paint.setTextSize(font_size.toFloat())
    
        /**
         * 话验证码
         */
        for (i in 0 until codeLength) {
            randomTextStyle(paint)
            randomPadding()
            val c1 = code!![i]
            c.drawText(code!![i] + "", padding_left.toFloat(), padding_top.toFloat(), paint)
        }
    
        /**
         * 画线条
         */
        for (i in 0 until line_number) {
            drawLine(c, paint)
        }
    
        c.save()
        c.restore()
        return bp
    }
    
    /**
     * 获取当前生成的二维码
     */
    fun getCode(): String? = code
    
    /**
     * 画线条
     */
    private fun drawLine(c: Canvas, paint: Paint) {
        val color = randomColor(1)
        val startX = random.nextInt(width).toFloat()
        val startY = random.nextInt(height).toFloat()
        val stopX = random.nextInt(width).toFloat()
        val stopY = random.nextInt(height).toFloat()
    
        paint.setStrokeWidth(1.toFloat());
        paint.setColor(color);
        c.drawLine(startX, startY, stopX, stopY, paint)
    
    }
    
    /**
     * 生成验证码
     */
    fun createCode(): String {
        val buffer = StringBuilder()
    
        for (i in 0 until codeLength) {
            buffer.append(CHARS[random.nextInt(CHARS.size)])
        }
        LogUtils.e(buffer.toString())
        return buffer.toString()
    }
    
    /**
     * 随机生成 文字样式,颜色,粗细,倾斜
     */
    fun randomTextStyle(paint: Paint) {
    
        val randomColor = randomColor(1)
        paint.setColor(randomColor)
        //random.nextBoolean() true 表示粗体,false 表示非粗体
        paint.setFakeBoldText(random.nextBoolean())
        var skewX = (random.nextInt(11) / 10).toFloat()
        skewX = if (random.nextBoolean()) skewX else -skewX
        //表示 flot 正数左斜 负数 右斜
        paint.textSkewX = skewX
    }
    
    /**
     * 随机生成颜色
     */
    private fun randomColor(rate: Int): Int {
        val red = random.nextInt(256) / rate
        val green = random.nextInt(256) / rate
        val blue = random.nextInt(256) / rate
        return Color.rgb(red, green, blue)
    }
    
    /**
     * 随机生成padding值
     */
    private fun randomPadding() {
        padding_left += base_padding_left + random.nextInt(range_padding_left)
        padding_top = base_padding_top + random.nextInt(range_padding_top)
    }
    }
    

    谢谢观看,如果有更好的优化方案可以留言谢谢~

    相关文章

      网友评论

          本文标题:kotlin 随机生成图片验证码

          本文链接:https://www.haomeiwen.com/subject/iqazwhtx.html