flutter绘制弧形进度条

在这里插入图片描述
绘制:

import 'package:jade/utils/JadeColors.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'package:flutter_screenutil/flutter_screenutil.dart';

class ArcProgressBar extends StatefulWidget{
  const ArcProgressBar({Key key}) : super(key: key);
  
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _ArcProgressBar();
  }
}

class _ArcProgressBar extends State<ArcProgressBar> with TickerProviderStateMixin{

  AnimationController controller;

  
  void initState() {
    // TODO: implement initState
    super.initState();
    controller = AnimationController(duration:const Duration(seconds: 1),lowerBound:0,upperBound:60,vsync: this);
    controller.addListener(() {
      setState(() {
        //   print(controller.value);
      });
    });
    controller.forward();
  }

  
  void dispose() {
    // TODO: implement dispose
    controller.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    // TODO: implement build
    return CustomPaint(
      painter: TestArcPainter(
          bgColor: JadeColors.lightGrey,
          sweepColor: Color(0xffFFC10F),
          strokeWidth: 45.0,
          progress: controller.value / 100),
      size: const Size(180.0,180.0), // 调整大小以适应你的需求
    );
  }
}

class TestArcPainter extends CustomPainter{

  ///进度百分比
  double progress;

  ///弧线宽度
  double strokeWidth;

  ///背景颜色
  Color bgColor;

  ///进度条颜色
  Color sweepColor;

  //整圆弧度
  final double wholeCirclesRadian=6.283185307179586;
  //圆被分割为160份
  final int tableCount= 12;

  TestArcPainter({
    this.strokeWidth,
    this.bgColor,
    this.sweepColor,
    this.progress});


  
  void paint(Canvas canvas, Size size) {
    // TODO: implement paint

    double cx = size.width / 2;
    double cy = size.height / 2;


    Paint _paint = Paint();
    //   ..color = Colors.red
    //   ..strokeWidth = 5;
    //
    // canvas.drawCircle(Offset(cx,cy), 2, _paint);
    // canvas.save();

    _paint = Paint()
      ..color = bgColor
      ..strokeWidth = strokeWidth
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.butt;

    double startDegree = degToRad(210);
    double sweepDegree = degToRad(120);

    Rect _rect = Rect.fromLTWH(0, 0, size.width, size.height);
    canvas.drawArc(_rect, startDegree, sweepDegree, false, _paint);
    canvas.save();
    canvas.restore();

    _paint = Paint()
      ..color = sweepColor
      ..strokeWidth = strokeWidth
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.butt;

    canvas.drawArc(_rect, startDegree, sweepDegree * progress, false, _paint);
    canvas.save();

    //计算三角函数公式 X= 圆中心点x + 半径 * cos(角度*3.14/180)
    //y=圆中心点y + 半径 * sin(角度*3.14/180)

    _paint
      ..color = Color(0xffF27800)
      ..style = PaintingStyle.fill
      ..strokeWidth = 3;
    double deg = startDegree + sweepDegree * progress;
    double x = cx + (cx + strokeWidth / 2) * math.cos(deg);
    double y = cy + (cy +strokeWidth / 2) *  math.sin(deg );
    // canvas.drawLine(Offset(cx, cy), Offset(x, y), _paint); //从圆形开始绘制的指针

    double x1 = cx + (cx - strokeWidth / 2) * math.cos(deg);
    double y1 = cy + (cy -strokeWidth / 2) *  math.sin(deg );

    canvas.drawLine(Offset(x1, y1), Offset(x, y), _paint); //从圆形开始绘制的指针
    canvas.restore();

    TextPainter textPainterCenter = TextPainter(
      text: TextSpan(children: [
        TextSpan(text: '¥', style: TextStyle(color: Colors.black,fontSize:40.sp)),
        TextSpan(text: '370.00', style: TextStyle(color: Colors.black,fontSize:66.sp,fontWeight: FontWeight.bold))
      ]),
      textDirection: TextDirection.ltr,
    );
    textPainterCenter.layout();
    textPainterCenter.paint(canvas, Offset(cx - (textPainterCenter.size.width / 2), cy - (textPainterCenter.size.height / 2)));
    canvas.save();
    canvas.restore();

    TextPainter textPainterCenterTwo = TextPainter(
      text: TextSpan(
        children: [
          TextSpan(text: '剩余金额', style: TextStyle(color: JadeColors.grey,fontSize:24.sp)),
          TextSpan(text: '(已退款)', style: TextStyle(color: JadeColors.orange_4,fontSize:24.sp)),
        ]
      ),
      textDirection: TextDirection.ltr,
    );
    textPainterCenterTwo.layout();
    textPainterCenterTwo.paint(canvas, Offset(cx - (textPainterCenterTwo.size.width / 2), cy + textPainterCenterTwo.size.height * 1.5));
    canvas.save();
    canvas.restore();

    double tableSpace = wholeCirclesRadian/tableCount;

    double textLeftX = cx + cx  * math.cos(startDegree);
    double textLeftY = cy + cy *  math.sin(startDegree) ;
    TextPainter textPainterLeft = TextPainter(
      text: TextSpan(text: '¥120000.00', style: TextStyle(color: JadeColors.grey,fontSize: 20.sp)),
      textDirection: TextDirection.ltr,
    );
    textPainterLeft.textDirection = TextDirection.ltr;
    textPainterLeft.layout();
    canvas.rotate(tableSpace);
    textPainterLeft.paint(canvas, Offset(textLeftX - (textPainterLeft.size.width / 8), textLeftY - (textPainterLeft.size.height / 2)));
    canvas.save();
    canvas.restore();

    double textRightX = cx + cx  * math.cos(startDegree + sweepDegree);
    double textRightY = cy +  cy *  math.sin(startDegree + sweepDegree) ;
    TextPainter textPainterRight = TextPainter(
      text: TextSpan(text: '¥1200000.00', style: TextStyle(color: JadeColors.grey,fontSize: 20.sp)),
      textDirection: TextDirection.ltr,
    );
    textPainterRight.layout();
    canvas.rotate(-(wholeCirclesRadian / 6));
    textPainterRight.paint(canvas, Offset(textRightX - textPainterRight.size.width * 1.2, textRightY + (textPainterRight.size.height * 6.4) ));
    canvas.save();
    canvas.restore();

/*

    ui.ParagraphBuilder paragraphBuilder = ui.ParagraphBuilder(ui.ParagraphStyle())..pushStyle(ui.TextStyle(color: Colors.black))..addText('100');
    ui.ParagraphConstraints paragraphConstraints = ui.ParagraphConstraints(width: size.width);
    ui.Paragraph paragraph = paragraphBuilder.build() ..layout(paragraphConstraints);

    canvas.drawParagraph(paragraph, Offset(cx - (textPainterCenter.size.width / 2), cy - (textPainterCenter.size.height / 2)));
*/


  }

  /// 角度转换弧度
  double degToRad(double deg) => deg * (math.pi / 180.0);

  
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return true;
  }
}

引用:(单纯绘制,相应数据未作处理)

Container(
   child: ArcProgressBar(),
   color: Colors.white
    )

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/155303.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统进程——进程的退出、子进程退出的收集、孤儿进程

进程退出 进程退出主要分为两种&#xff1a;正常退出、异常退出 正常退出 正常退出分为以下几种&#xff1a; 1.main函数调用return 2.进程调用exit(),标准c库 3.进程调用 _exit() 或者 _Exit() &#xff0c;属于系统调用 4.进程最后一个线程返回 5.最后一个线程调用pthrea…

晨控CK-FR08读卡器与汇川PLC连接EtherCAT通讯手册

晨控CK-FR08读卡器与汇川PLC连接EtherCAT通讯手册 晨控CK-FR08系列是一款基于射频识别技术的高频RFID标签读卡器&#xff0c;读卡器工作频率为13.56MHZ&#xff0c;支持对I-CODE 2、I-CODE SLI等符合ISO15693国际标准协议格式标签的读取。 读卡器同时支持标准工业通讯协议Eth…

ubuntu20源码编译搭建SRS流媒体服务器

第一、下载源码 下载源码&#xff0c;推荐用Ubuntu20&#xff1a; git clone -b develop https://gitee.com/ossrs/srs.git第二、编译 2.1、切换到srs/trunk目录&#xff1a; cd srs/trunk2.2、执行configure脚本 ./configure2.3、执行make命令 make2.4、修改conf/rtmp.c…

通讯录实现之进阶版将通讯录数据保存在文件中(完整代码)

我们在之前的博客中已经写过两版通讯录了&#xff1a; 第一版是用C语言实现了通讯录&#xff0c;但是通讯录的存储人数信息是固定的&#xff0c;用完就没有了 感兴趣的可以转到对应博客看一下&#xff0c;附带链接&#xff1a;第一版通讯录 第二版是在第一版的基础上动态开辟…

从零开始 通义千问大模型本地化到阿里云通义千问API调用

从零开始 通义千问大模型本地化到阿里云通义千问API调用 一、通义千问大模型介绍 何为“通义千问”&#xff1f; “通义千问大模型”是阿里云推出的一个超大规模的语言模型&#xff0c;具有强大的归纳和理解能力&#xff0c;可以处理各种自然语言处理任务&#xff0c;包括但…

DAC实验(DAC 输出三角波实验)(DAC 输出正弦波实验)

DAC 输出三角波实验 本实验我们来学习使用如何让 DAC 输出三角波&#xff0c;DAC 初始化部分还是用 DAC 输出实验 的&#xff0c;所以做本实验的前提是先学习 DAC 输出实验。 使用 DAC 输出三角波&#xff0c;通过 KEY0/KEY1 两个按键&#xff0c;控制 DAC1 的通道 1 输出两种…

文旅媒体有哪些?如何邀请到现场报道?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 中国文旅产业在近年来得到了持续而快速的发展。从产业端看&#xff0c;中国文旅产业呈现出新的发展趋势&#xff0c;其中“文旅”向“文旅”转变成为显著特点。通过产业升级和空间构建&a…

Shell编程基础(3)- Shell的位置参数

Shell编程基础&#xff08;3&#xff09;- Shell的位置参数 Shell Scripting Essentials (3) – Locative Parameters of Shell Scripting 前文介绍过shell变量。当声明shell变量时&#xff0c;只需要在代码行写出变量名称即可;在输入行用read命令要求用户输入&#xff0c;在…

Day48 力扣动态规划 : 647. 回文子串 |516.最长回文子序列 |动态规划总结篇

Day48 力扣动态规划 : 647. 回文子串 &#xff5c;516.最长回文子序列 &#xff5c;动态规划总结篇 647. 回文子串第一印象看完题解的思路dp递推公式初始化递归顺序 实现中的困难感悟代码 516.最长回文子序列第一印象我的尝试遇到的问题 看完题解的思路dp递推公式初始化 实现中…

设计基于STM32F103C8T6微控制器的巡线小车

巡线小车是一种能够在一条预定线追踪路径的小车&#xff0c;广泛应用于工业自动化、物流仓储、智能家居等领域。本设计将使用STM32F103C8T6微控制器来实现一个基础的巡线小车。 硬件组成&#xff1a;1. STM32F103C8T6微控制器开发板&#xff1a;作为巡线小车的核心控制器&…

双剑合璧:基于Elasticsearch的两路召回语义检索系统,实现关键字与语义的高效精准匹配

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

NewStarCTF2023 Reverse Week3 EzDLL WP

分析 这里调用了z3h.dll中的encrypt函数。 用ida64载入z3h.dll 直接搜索encrypt 找到了一个XTEA加密。接着回去找key和密文。 发现key 这里用了个调试状态来判断是否正确&#xff0c;v71&#xff0c;要v7&#xff1d;1才会输出Right&#xff0c;即程序要处于飞调试状态。 可…

asp.net core EF Sqlserver

一、EF CORE的使用 1、使用NuGet来安装EF CORE 使用程序包管理器控制台&#xff0c;进行命令安装 //安装 Microsoft.EntityFrameworkCoreInstall-Package Microsoft.EntityFrameworkCore //安装 Microsoft.EntityFrameworkCore.SqlServer Install-Package Microsoft.EntityF…

Java智慧工地云SaaS源码,AI服务器、智能硬件

智慧工地智能硬件 一、自动喷淋控制 当扬尘监测值超过在智慧工地系统中设定的闽值后自动喷淋控制系统通过接收系统发出的开关指令&#xff0c;实现自动、及时喷淋降尘&#xff0c;同时系统可设置自动喷淋时间段&#xff0c;每天定时喷淋&#xff0c;避免环境污染。 二、智能电…

采用Nexus搭建Maven私服

采用Nexus搭建Maven私服 1.采用docker安装 1.创建数据目录挂载的目录&#xff1a; /usr/local/springcloud_1113/nexus3/nexus-data2.查询并拉取镜像docker search nexus3docker pull sonatype/nexus33.查看拉取的镜像docker images4.创建docker容器&#xff1a;可能出现启动…

【vue】下载导出excel

下载导出excel 首先使用的tdesign框架&#xff0c;要导出后端返回的数据流excel 遇见的问题 下载的文件&#xff0c;里边的内容是undefined 观察报错 一看就知道并不是后端的报错&#xff0c;后端不可能是undefined 在强烈的好奇心驱动下&#xff0c;看了下接口&#xff0…

Docker安装MinIO遇到的(汇总——持续更新中)

文章目录 Docker安装MinIO遇到的坑前言问题1&#xff1a;执行docker run报错Error response from daemon问题2&#xff1a;启动MinIO容器浏览器无法访问问题3&#xff1a;上传文件报错InvalidResponseException问题4&#xff1a;上传文件报错Connection refused最终的启动指令问…

【Electron】electron-builder打包失败问题记录

文章目录 yarn下载的包不支持require()winCodeSign-2.6.0.7z下载失败nsis-3.0.4.1.7z下载失败待补充... yarn下载的包不支持require() 报错内容&#xff1a; var stringWidth require(string-width)^ Error [ERR_REQUIRE_ESM]: require() of ES Module /stuff/node_modules/…

轮播图(多个一起轮播)

效果图 class MainActivity : Activity(), Runnable {private lateinit var viewPager: ViewPagerprivate lateinit var bannerAdapter: BannerAdapterprivate val images ArrayList<Int>() // 存储图片资源的列表private val handler Handler() // 用于定时发送消息…

Linux磁盘分区快速上手(讲解详细)

一、磁盘分区 在Linux中&#xff0c;磁盘是通过分区来使用的。分区是将一个硬盘划分成几个逻辑部分来使用&#xff0c;在每个分区中可以存储不同的文件系统。因此&#xff0c;在挂载磁盘之前&#xff0c;我们需要先对磁盘进行分区。磁盘分区的过程可以通过命令行工具或图形界面…