Flutter 开发 一个 字母+数字的随机数图片验证码

Flutter 一个 字母+数字的随机数图片验证码

废话不多说,首先上效果图
在这里插入图片描述

使用方法:
 @override
  void initState() {
    super.initState();
    _getCode();
  }

// 调用随机数方法
  _getCode(){
    code = '';
    String alphabet = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM';
    for (var i = 0; i < 4; i++) {
      String charOrNum = Random().nextInt(2) % 2 == 0 ? "char" : "num";  
      switch (charOrNum) {
          case "char":
              code += alphabet[Random().nextInt(alphabet.length)];
              break;
          case "num":
              code += Random().nextInt(9).toString();
              break;
      }
      setState(() {});
    }
  }

// Widget
InkWell(
  child:Container(
    padding: EdgeInsets.only(left:ScreenAdapter.setWidth(10)),
    decoration: BoxDecoration(
      color: Colors.white,
      border:Border(
        left:BorderSide(
          width:ScreenAdapter.setWidth(1),
          color:Color(0xffC7C7C7)
        )
      )
    ),
    child:CustomVertificationCode(
      code: code,
    )
  ),
  onTap:(){
    _getCode();
  }
)
生成随机数代码:
import 'package:flutter/material.dart';
import 'dart:math';

class CustomVertificationCode extends StatefulWidget {
  final String code;
  final int dotCount;
  final double width;
  final double height;
  final Color backgroundColor;

  const CustomVertificationCode(
      {Key key,
      @required this.code,
      this.backgroundColor,
      this.dotCount = 50,
      this.width = 120,
      this.height = 40})
      : super(key: key);

  @override
  _CustomVertificationCodeState createState() => _CustomVertificationCodeState();
}

class _CustomVertificationCodeState extends State<CustomVertificationCode> {
  //随机生成绘图数据
  Map getRandomData() {
    // 数字list
    List list = widget.code.split("");
    // X坐标
    double x = 0.0;
    // 最大字体大小
    double maxFontSize = 35.0;
    //将painter保存起来,先计算出位置
    List mList = [];
    for (String item in list) {
      Color color = Color.fromARGB(255, Random().nextInt(255),
          Random().nextInt(255), Random().nextInt(255));
      int fontWeight = Random().nextInt(9);
      TextSpan span = TextSpan(
          text: item,
          style: TextStyle(
              color: color,
              fontWeight: FontWeight.values[fontWeight],
              fontSize: maxFontSize - Random().nextInt(10)));
      TextPainter painter =
          TextPainter(text: span, textDirection: TextDirection.ltr);
      painter.layout();
      double y =
          Random().nextInt(widget.height.toInt()).toDouble() - painter.height;
      if (y < 0) {
        y = 0;
      }
      Map strMap = {"painter": painter, "x": x, "y": y};
      mList.add(strMap);
      x += painter.width + 3;
    }
    double offsetX = (widget.width - x) / 2;
    List dotData = [];
    //绘制干扰点
    for (var i = 0; i < widget.dotCount; i++) {
      int r = Random().nextInt(255);
      int g = Random().nextInt(255);
      int b = Random().nextInt(255);
      double x = Random().nextInt(widget.width.toInt() - 5).toDouble();
      double y = Random().nextInt(widget.height.toInt() - 5).toDouble();
      double dotWidth = Random().nextInt(6).toDouble();
      Color color = Color.fromARGB(255, r, g, b);
      Map dot = {"x": x, "y": y, "dotWidth": dotWidth, "color": color};
      dotData.add(dot);
    }

    Map checkCodeDrawData = {
      "painterData": mList,
      "offsetX": offsetX,
      "dotData": dotData,
    };
    return checkCodeDrawData;
  }

  @override
  Widget build(BuildContext context) {
    print("buid?");
    double maxWidth = 0.0;
    Map drawData = getRandomData();
    //计算最大宽度做自适应
    maxWidth = getTextSize("8" * widget.code.length,
            TextStyle(fontWeight: FontWeight.values[8], fontSize: 25))
        .width;
    return Container(
        color: widget.backgroundColor,
        width: maxWidth > widget.width ? maxWidth : widget.width,
        height: widget.height,
        child: CustomPaint(
          painter: CustomVertificationCodePainter(drawData: drawData),
        ));
  }

  Size getTextSize(String text, TextStyle style) {
    final TextPainter textPainter = TextPainter(
        text: TextSpan(text: text, style: style),
        maxLines: 1,
        textDirection: TextDirection.ltr)
      ..layout(minWidth: 0, maxWidth: double.infinity);
    return textPainter.size;
  }
}

class CustomVertificationCodePainter extends CustomPainter {
  final Map drawData;
  CustomVertificationCodePainter({
    @required this.drawData,
  });

  Paint _paint = new Paint()
    ..color = Colors.grey
    ..strokeCap = StrokeCap.square
    ..isAntiAlias = true
    ..strokeWidth = 1.0
    ..style = PaintingStyle.fill;
  @override
  void paint(Canvas canvas, Size size) {
    List mList = drawData["painterData"];

    double offsetX = drawData["offsetX"];
    //为了能��居中显示移动画布
    canvas.translate(offsetX, 0);
    //从Map中取出值,直接绘制
    for (var item in mList) {
      TextPainter painter = item["painter"];
      double x = item["x"];
      double y = item["y"];
      painter.paint(
        canvas,
        Offset(x, y),
      );
    }
    // //将画布平移回去

    canvas.translate(-offsetX, 0);
    List dotData = drawData["dotData"];
    for (var item in dotData) {
      double x = item["x"];
      double y = item["y"];
      double dotWidth = item["dotWidth"];
      Color color = item["color"];
      _paint.color = color;
      canvas.drawOval(Rect.fromLTWH(x, y, dotWidth, dotWidth), _paint);
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return this != oldDelegate;
  }
}

感谢 hb_check_code 提供技术帮助!

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值