Compose Text + Canvas 写个验证码

本文档介绍如何使用Jetpack Compose实现一个登录验证码功能,包括验证码的随机生成、样式设置、干扰线绘制以及响应式刷新。通过组合Text和Canvas组件,结合随机数和属性随机化,创建出具有不同样式的验证码。同时,文章提供了完整的代码示例,包括验证码的生成、保存、验证以及点击刷新功能。

前言

在搞登录功能时,想弄个登录验证码,在网上溜了一圈好像还没有用 Compose 写过的(可能是没搜到),既然没有就自己搞一个吧。
大家如果没时间或者基础好可以直接去完整代码 看核心代码,因为实现比较简单,也比较重复。当然我也是很欢迎你阅读我的文章和我一步步学习的。


一、工具选择

网上大部分都是用 paint 来实现的,但是在 Compose 里 paint 的属性好像有所减少,就比如 textSkewX 就没有(下为 Compose ):在这里插入图片描述
在这里插入图片描述
既然这样用 paint 就不大好了。最后想到,验证码一般包括字母和数字,那就直接用最简单的 Text 加 canvas 来呗。


二、基本思想

验证码最重要的是随机性,那我们如何做到随机呢?这不是很简单吗,用 Random 啊。那验证码的样式如何做到不同呢?这不是很简单吗,用 Random + 属性啊。所以我们只要罗列 Text 的属性,配上 Random 就能得到验证码的基本样式了:
在这里插入图片描述
那上面说到的 canvas 拿来干嘛呢,它其实是用来画干扰线的,最后的效果是这样的(应该还行):
在这里插入图片描述
可能有更好的想法,但是我不会。下面我们来举一例讲讲具体实现。


三、具体实现

0、参数解释

这里先放上最后实现验证码所需要的参数并解释一下,便于大家后面的阅读:

@RequiresApi(Build.VERSION_CODES.Q)
@OptIn(ExperimentalUnitApi::class)
@Composable
fun VerifyCode(
    // 宽高不用解释
    width: Dp,
    height: Dp,
    // 距离左上角的的偏移量, 用于定位
    topLeft: DpOffset = DpOffset.Zero,
    // 验证码的数量
    codeNum: Int = 4,
    // 干扰线的数量
    disturbLineNum: Int = 10,
    // 用于保存验证码, 用于用户输入时进行验证
    viewModel: MyViewModel
) {
   
   }

1、验证内容

最先要实现的当然是的要验证的东西啦,像这样:

private val codeList = listOf(
        "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"
    )

我们用数字和字母进行验证,在后面我会随机挑选 codeNum 个用来作为验证码。

2、Text设置

根据上面所说的 Random + 属性的想法。我们先得到 Text 的所有属性:

Text(
    text = ,
    modifier = ,
    color = ,
    fontSize = ,
    fontStyle = ,
    fontWeight = ,
    fontFamily = ,
    textDecoration = ,
    textAlign = ,
    letterSpacing = ,
    lineHeight = ,
    maxLines =,
    onTextLayout =,
    style =,
)

并且罗列所有将要赋予属性的值(这里以 fontFamily 为例):

    private val fontFamilyList = listOf(
        FontFamily.Default,
        FontFamily.Cursive,
        FontFamily.Monospace,
        FontFamily.SansSerif,
        FontFamily.Serif
    )

下面是各个用到的属性的所有值,大家如果想看可以前往完整代码先偷窥一下再回头来继续学习。
在这里插入图片描述
加上 Random :

    private fun <T> List<T>.getRandom() = this[Random.nextInt(this.size)]
//    shuffled() 函数返回⼀个包含了以随机顺序排序的集合元素的新的 List
//    private fun <T>  List<T>.getRandom() : T = this.shuffled().take(1)[0]

这里用了 kotlin 的扩展函数(用起来真的爽),有两种写法大家自选。
最后的得到这样的结果:

Text(
    text = Code.getCode(),
    modifier = Modifier
        .width(width / codeNum)
        .height(height)
        .offset(topLeft.x + dx, topLeft.y),
    color = Code.getColor(),
    // 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值