当前位置: 首页 > news >正文

Flutter---坐标网格图标

效果图

Flutter本身没有直接绘制虚线的内置组件,所以需要自定义画虚线的工具类

import 'package:flutter/material.dart';//绘制垂直虚线的工具类
class DashPainter extends CustomPainter {//1.定义常量final Color color;final double strokeWidth;final double dashWidth;final double dashSpace;//2.构造函数DashPainter({this.color = Colors.black, //虚线颜色,默认黑色this.strokeWidth = 1.0, //线宽,默认1像素this.dashWidth = 3.0,//每个短划的长度,默认3像素this.dashSpace = 2.0,//短滑之间的距离,默认2像素});@overridevoid paint(Canvas canvas, Size size) { //size(215)来自CustomPaint的size属性,size由Flutter自动传入//3.创建画笔final paint = Paint()..color = color//设置颜色..strokeWidth = strokeWidth//设置线宽..style = PaintingStyle.stroke;//设置为描边模式// 4.计算x坐标,让线条在容器中居中final x = strokeWidth / 2;double startY = 0;//起始Y坐标//5.循环直到画满整个高度while (startY < size.height) {//绘制一个短划canvas.drawLine(Offset(x, startY), //起点坐标,X坐标固定,Y变化,所以是绘制垂直线Offset(x, startY + dashWidth),//终点坐标,X坐标固定,Y变化,所以是绘制垂直线paint,//使用的画笔);//移动到下一个短划的起始位置startY += dashWidth + dashSpace;}}@overridebool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

使用方式

           Positioned( //确定位置left: 280 / 4,//水平位置child: CustomPaint(//设置画布size: Size(0.5, 215), // 宽度0.5,高度215painter: DashPainter(color: Color(0xFF878787),strokeWidth: 0.5,//线条粗细dashWidth: 3,//每段虚线长度dashSpace: 2,//虚线间隔),),),

数据流

Positioned → CustomPaint → DashPainter构造函数 → paint方法 → 绘制到屏幕↓            ↓              ↓              ↓          ↓
位置定位     设置画布大小    接收绘制参数    执行绘制逻辑   显示虚线

①Positioned定位:left = 70

②CustomPaint设置画布,画布大小:宽0.5px,高215px

③DashPainter 构造函数接收参数

④paint 方法拿到参数,创建画笔和计算参数: x = 0.5 ÷ 2 = 0.25(居中位置),Y默认为0

⑤执行循环划线的方法,直到Y大于215

⑥虚线画完,显示在屏幕上

完整调用栈

1. Flutter框架构建Positioned
2. Positioned创建CustomPaint
3. CustomPaint创建DashPainter实例
4. DashPainter构造函数保存参数
5. Flutter调用DashPainter.paint()
6. paint()方法执行绘制循环
7. 43次canvas.drawLine()调用
8. 结果显示在屏幕上

代码实例


import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:my_flutter/dash_painter.dart';class HomePage extends StatefulWidget{const HomePage({super.key});@overrideState<StatefulWidget> createState() => _HomePageState();}class _HomePageState extends State<HomePage>{//UI构建@overrideWidget build(BuildContext context) {return Scaffold(body: Padding(padding: EdgeInsets.only(left: 20,top: 200),//内边距child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [// Y轴坐标标签和表格行Row(crossAxisAlignment: CrossAxisAlignment.start,children: [// Y轴标签(左侧)Container(width: 20,height: 215,child: Column(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Text('180', style: TextStyle(fontSize: 10)),Text('120', style: TextStyle(fontSize: 10)),Text('60', style: TextStyle(fontSize: 10)),Text('0', style: TextStyle(fontSize: 10)),],),),// 表格主体_buildTodayTable(),],),// X轴坐标标签(底部)Container(padding: EdgeInsets.only(left: 20, right: 45),width: 305,child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Text("0时", style: TextStyle(fontSize: 10)),Text("6时", style: TextStyle(fontSize: 10)),Text("12时", style: TextStyle(fontSize: 10)),Text("18时", style: TextStyle(fontSize: 10)),],),),],),),);}//表格的主体Widget _buildTodayTable() {return Container(width: 280,height: 215,decoration: BoxDecoration(//边框border: Border(left: BorderSide(color: Color(0xFF878787), width: 0.5),right: BorderSide(color: Color(0xFF878787), width: 0.5),bottom: BorderSide(color: Color(0xFF878787), width: 0.5),top: BorderSide(color: Color(0xFF878787), width: 0.5),),),child: Stack(children: [// 第一条中间水平线Positioned(top: 215 / 3,child: Container(width: 305,height: 0.5,color: Color(0xFF878787),),),// 第二条中间水平线Positioned(top: 215 * 2 / 3,child: Container(width: 305,height: 0.5,color: Color(0xFF878787),),),// 垂直线(全虚线)Positioned( //确定位置left: 280 / 4,//水平位置child: CustomPaint(//设置画布size: Size(0.5, 215), // 宽度0.5,高度215painter: DashPainter(color: Color(0xFF878787),strokeWidth: 0.5,//线条粗细dashWidth: 3,//每段虚线长度dashSpace: 2,//虚线间隔),),),Positioned(left: 280 / 2,child: CustomPaint(size: Size(0.5, 215),painter: DashPainter(color: Color(0xFF878787),strokeWidth: 0.5,dashWidth: 3,dashSpace: 2,),),),Positioned(left: 280 * 3 / 4,child: CustomPaint(size: Size(0.5, 215),painter: DashPainter(color: Color(0xFF878787),strokeWidth: 0.5,dashWidth: 3,dashSpace: 2,),),),],),);}
}

http://www.dtcms.com/a/486679.html

相关文章:

  • 邢台做网站多少钱洪泽网站建设
  • 整体设计 逻辑系统程序 之30 定稿V1 之1 含 4 套程序架构、三式模型与时空约束体系
  • 基于单片机的智能洗衣机的设计与实现(论文+源码)
  • 【ComfyUI】SDXL Revision 文本提示实现参考图像概念迁移生成
  • Zabbix 模板、监控项、图形指南
  • 个人如何做网站软件湛江免费制作网站
  • 嘉兴公司网站模板建站建设厅官方网站
  • 【javaFX基础】javaFX文档学习及基础编程实践
  • [c++语法学习]Day10:c++引用
  • iOS App 上架全流程详解:证书配置、打包上传、审核技巧与跨平台上架工具 开心上架 实践
  • C++设计模式_行为型模式_迭代器模式Iterator
  • [iOS] KVC 学习
  • 网站开发中用到的英文单词舅舅建筑网
  • 怎么做交易网站seo整体优化
  • 基于卷积神经网络的苹果叶片病虫害识别系统,resnet50,vgg16,resnet34【pytorch框架,python代码】
  • 【计算机组成原理】第七章:输入/输出系统
  • 深入理解 Linux NUMA:拓扑、分配策略与调优实践
  • logstash常遇问题(logstash Address already in use 5044)
  • 断点调试介绍与使用案例
  • Kafka在美团数据平台的实践
  • 【完整源码+数据集+部署教程】Aura棕榈油果实分割系统: yolov8-seg-C2f-DCNV2-Dynamic
  • 蛋白表达标签:提升重组蛋白研究与生产的关键工具
  • 网站备案编号查询wordpress 集成paypal
  • 数学口算练习抖音快手微信小程序看广告流量主开源
  • 【开题答辩过程】以《泰山珍稀动植物信息管理平台的设计与实现》为例,不会开题答辩的可以进来看看
  • wordpress 淘宝客页面seo网络培训班
  • 哪些公司做网站wordpress单选框php
  • 什么是程序计数器?
  • GEO实战之GEO 在营销生态中的定位:社交媒体、PR、内容营销的整合策略
  • 10.13 Tabs选项卡布局