Flutter 实现“斑马纹”背景

由于工作中项目需求,需要将H5转换为Flutter代码。

其中的斑马纹背景需要根据接口返回的颜色来渲染,所以不能只是图片形式,无法通过decoration属性配置图片背景板。

楼主这边想到的方法就是通过 实现一个canvas绘制斑马纹类。使用Stack布局,将斑马纹放在下方作为背景板,需要展示的内容在上方。

实现 “斑马纹”背景(需要变换颜色)

文章主要分为 效果图、实现思维、代码、计算过程解释。希望对大家有所帮助

最终效果图

实现思维

斑马纹(45°角,向左倾斜)

使用CustomPaint(size: Size(width, height), painter: 画笔)

  1. CustomPaint(
  2. size: Size(widget.width, widget.height),
  3. painter: 画笔,
  4. )

画笔

继承 CustomPainter类,实现paint(Canvas canvas, Size size)方法,根据 宽度、高度、画笔宽度、间距 计算出各个点位。使用canvas. drawLine方法 绘制出斑马纹。

  1. @override
  2. void paint(Canvas canvas, Size size) {

  3. canvas. drawLine();
  4. }

斑马纹坐标位置计算

2.82 = 2倍根号2

1.41 = 根号二

填充个数= 最大高度 / (画笔宽度1.41+间距) 向上取整。(从0, 0开始,左侧会露出空位,所以需要填充)

条纹个数 = 宽度/(画笔宽度
1.41+间距) 向上取整。

(x轴y轴) 偏移量 =画笔宽度 / 2.82 (画笔起始点、结束点会露出一小节,需要计算x,y偏移量。将左上角x,y减去偏移量,右下角x,y加上偏移量,补充此部分)

起点坐标 =((画笔宽度1.41+间距) * 条纹index – 偏移量,– 偏移量)

终点坐标 =((画笔宽度
1.41+间距) * 条纹index - 偏移量+高度, 高度+偏移量)

圆角裁剪(如果需要)

由于画笔绘制的是直角的,所以作为背景板会超出,需要裁剪掉四个角。使用

  1. ClipRRect(
  2. borderRadius: BorderRadius.all(Radius.circular(10)),
  3. child: xxx
  4. )

作为背景

使用Stack布局,实现斑马纹在下方作为背景板,需要展示的内容在上方

  1. Stack(
  2. children: [
  3. buildZebraBack(…),
  4. 需要展示的内容
  5. ]
  6. )

代码

使用处 main_page.dart

  1. Stack(
  2. children: [
  3. Positioned(
  4. child: ZebraStripesBack(
  5. width: 335,
  6. height: 44,
  7. lineWidth: 10,
  8. spacing: 10,
  9. borderRaduis: 10,
  10. lineColor: Colors.blue),
  11. top: 0,
  12. left: 0,
  13. ),
  14. Container(
  15. width: 335,
  16. height: 44,
  17. alignment: Alignment.center,
  18. padding: EdgeInsets.only(
  19. top: 10,
  20. left: 12,
  21. bottom: 10,
  22. right: 12),
  23. child: Text(
  24. "英语",
  25. style: TextStyle(
  26. color: Color(0xFFFFFFFF),
  27. fontSize: 14.sp,
  28. fontWeight: FontWeight.w500),
  29. )
  30. )
  31. ]
  32. )

斑马纹具体实现类 zebra_stripes_back.dart

  1. import 'dart:math';
  2. import 'package:flutter/material.dart';
  3. // 斑马纹具体实现类
  4. class ZebraStripesBack extends StatefulWidget {
  5. ZebraStripesBack({
  6. this.width: 0,
  7. this.height: 0,
  8. this.spacing: 4,
  9. this.lineWidth: 4,
  10. this.lineColor: Colors.transparent,
  11. this.borderRaduis: 0,
  12. });
  13. final double width; // 容器宽度
  14. final double height; // 容器高度
  15. final double lineWidth; // 斑马纹宽度
  16. final double spacing; // 间距
  17. final double borderRaduis; // 容器圆角
  18. final Color lineColor; // 斑马纹颜色
  19. @override
  20. State<StatefulWidget> createState() => _ZebraStripesBackState();
  21. }
  22. class _ZebraStripesBackState extends State<ZebraStripesBack> {
  23. @override
  24. void initState() {
  25. super.initState();
  26. }
  27. @override
  28. void dispose() {
  29. super.dispose();
  30. }
  31. @override
  32. Widget build(BuildContext context) {
  33. return ClipRRect(
  34. borderRadius: BorderRadius.all(Radius.circular(widget.borderRaduis)),
  35. child: CustomPaint(
  36. size: Size(widget.width, widget.height),
  37. painter: _ZebraStripesBackPainter(
  38. maxWidth: widget.width,
  39. maxHeight: widget.height,
  40. spacing: widget.spacing,
  41. lineWidth: widget.lineWidth,
  42. lineColor: widget.lineColor,
  43. borderRaduis: widget.borderRaduis,
  44. ),
  45. ));
  46. }
  47. }
  48. class _ZebraStripesBackPainter extends CustomPainter {
  49. _ZebraStripesBackPainter({
  50. this.maxWidth: 0,
  51. this.maxHeight: 0,
  52. this.spacing: 4,
  53. this.lineWidth: 4,
  54. this.lineColor: Colors.black12,
  55. this.borderRaduis: 0,
  56. });
  57. final double maxWidth;
  58. final double maxHeight;
  59. final double spacing;
  60. final double lineWidth;
  61. final Color lineColor;
  62. final double borderRaduis;
  63. @override
  64. void paint(Canvas canvas, Size size) {
  65. var paint = Paint()
  66. ..isAntiAlias = true
  67. ..style = PaintingStyle.fill
  68. ..color = lineColor
  69. ..strokeWidth = lineWidth;
  70. int number = 0; // 个数
  71. int fillNumber = 0; // 填充个数
  72. double lineAndSpace = lineWidth *1.41 + spacing; // 单个条纹宽 + 间距宽
  73. if (lineWidth > 0) {
  74. number = (maxWidth / lineAndSpace).ceil();
  75. fillNumber = (maxHeight / lineAndSpace).ceil(); // 填充个数
  76. }
  77. double deviation = lineWidth / 2.82; // x y轴偏移量 = width / 2倍根号2
  78. for (int i = -fillNumber; i < number; i++) {
  79. var left = lineAndSpace * i - deviation;
  80. double dx = left;
  81. double dy = -deviation;
  82. double dx1 = left + maxHeight;
  83. double dy1 = maxHeight + deviation;
  84. canvas.drawLine(
  85. Offset(dx, dy),
  86. Offset(dx1, dy1),
  87. paint,
  88. );
  89. }
  90. }
  91. @override
  92. bool shouldRepaint(CustomPainter oldDelegate) => true;
  93. }

计算过程解释

偏移量计算过程

填充个数计算过程

为什么画笔宽度需要乘 根号二?

缺少-填充

缺少-偏移量

Flutter 实现“斑马纹”背景(需要变换颜色)的更多相关文章

  1. 计算机中的颜色XIV——快速变换颜色的V分量

    基本知识回顾: 计算机中的颜色Color,用RGB模式存储(用R.G.B三个分量表示颜色,每个分量的范围是0—255). 而计算机中的颜色除了用RGB模式表示以外,常见的还有HSV模式(或者是HSB. ...

  2. phpstorm调整背景、字体颜色

    从这个网站(http://phpstorm-themes.com/)下载各类主题的xml文件, 然后将文件放到phpStorm的文件夹中,比如:C:\Users\USERNAME\.PhpStorm2 ...

  3. HTML快速入门5——不规则表格、表格背景、边框颜色

    转自:http://blog.csdn.net/ysuncn/article/details/2214153 不规则表格 例子: <table border=1><tr>< ...

  4. 【JavaScript】轻易改变的背景和字体颜色页面

    JavaScript,点击button改变页面背景和字体颜色,网页有N颜色的变化button.点击不同button,网页字体和背景将被改变为不同的颜色. 非常easy的JavaScript小程序. 一 ...

  5. 设置LISTControl控件某一行的背景和文字颜色

    定义宏 用listcontrol的SetItemData设置某一行的属性,通过自定义属性标识实现. 自定义某行内容颜色属性: #define COLOR_DEFAULT 0 //默认颜色 #defin ...

  6. navigationItem.rightBarButtonItem 设置背景图片,颜色更改解决的方法

    self.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@& ...

  7. Android中通过xml改变背景及文字颜色

    原创文章,转载请注明出处,谢谢! 本篇主要介绍Android开发中,通过XML资源文件来设置控件在不同状态下的背景及文字颜色.关于xml改变背景及文字颜色的原理,大家可以去看一下郭霖大神的源码分析文章 ...

  8. (转)Android 自定义 spinner (背景、字体颜色)

    Android 自定义 spinner (背景.字体颜色) (2012-07-04 17:04:44)   1.准备两张图片,并做好9.png   2.在drawable中定义spinner_sele ...

  9. 通过C语言程序改动控制台的背景和前景颜色

    本文主要解说怎样通过C语言来改动dos背景和前景颜色.我们首先来看一下dos的背景颜色的属性. 打开開始菜单,点击执行,弹出执行对话框.输入cmd,回车. (打开dos控制台) 在命令提示符界面下,输 ...

随机推荐

  1. Kubernetes 解决方案-图解

  2. 两数之和II_LeetCode_167_1099

    LeetCode_167原题链接:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ LeetCode_1099原题链 ...

  3. STL空间分配器源码分析(三)pool_allocator

    一.摘要 pool_allocator是一种基于单锁内存池的空间分配器,其内部采用内存池思想,通过构建16个空闲内存块队列,来进行内存的申请和回收处理.每个空闲队列管理的内存块大小固定,且均为8的倍数 ...

  4. 对比学习 ——simsiam 代码解析。

    ​  目录 1 : 事先准备 . 2 : 代码阅读. 2.1: 数据读取 2.2: 模型载入 3 训练过程: 4 测试过程: 5 :线性验证 6 : 用自己数据集进行对比学习. 第一:  改数据集 : ...

  5. 开源框架YiShaAdmin如何使用任务计划

    1.在Startup添加 new JobCenter().Start();(红色字体,下同) // This method gets called by the runtime. Use this m ...

  6. OSPF MTU问题

    OSFP(开放式最短路径优先)链路状态协议,IGP 1.mtu 检测 链路俩段不匹配 假设双方的mtu不一致时 ospf建立如下: R1与R2交互hello报文,其中包含:目的IP地址:224.0.0 ...

  7. 【FAQ】接入HMS Core地图服务过程中常见问题总结

    HMS Core地图服务(Map Kit)给开发者提供一套地图开发调用的SDK,助力全球开发者实现个性化地图呈现与交互,方便轻松地在应用中集成地图相关的功能,全方位提升用户体验. 在日常工作中,我们会 ...

  8. 使用fastai训练的一个性别识别模型

    在学习了python中的一些机器学习的相关模块后,再一次开始了深度学习之旅.不过与上次的TensorFlow框架不同,这一次接触的是fast.ai这样一个东西.这个框架还不稳定,网上也没有相关的中文文 ...

  9. Linux-流程控制语法-函数-属组

    1.流程控制 1.1 条件选择 1.1.1选择执行if语句 格式: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ] ... ...

  10. js实时查询,为空提示

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...