Flutter 实现“斑马纹”背景
由于工作中的项目需求,需要将H5转换为Flutter代码。
斑马纹背景需要根据界面返回的颜色进行渲染,不能只是图片的形式,也不能通过decoration属性配置图片背景板。
楼主在这里想到的方法是通过实现一个canvas来绘制斑马纹。使用Stack布局,下面的斑马纹作为背景板,上面要显示的内容。
实现“斑马”背景(需要改变颜色)
文章主要分为效果图、实现思路、代码、计算过程讲解。希望对你有帮助
最终渲染
思维斑马纹的实现(45°角,向左倾斜)
使用CustomPaint(size: Size(width, height),painter:brush)
CustomPaint(
size: Size(widget.width, widget.height),
painter: 画笔,
)
刷
继承CustomPainter类,实现paint(Canvas canvas, Size size)方法,根据宽度、高度、画笔宽度、间距计算每个点。使用canvas.drawLine方法绘制斑马纹。
@override
void paint(Canvas canvas, Size size) {
…
canvas. drawLine();
}
斑马纹坐标位置的计算
2.82 = 2 次根 2
1.41 = 根二
填充数 = 最大高度/(画笔宽度1.41+间距)向上取整。 (从0开始,0开始,左边会有空位,所以需要补上)
条纹数 = 宽度/(画笔宽度1.41+间距)向上取整。
(x-axis y-axis) offset =画笔宽度/2.82(画笔的起点和终点都会露出一段,需要计算x,y偏移量。减去上边left corner x, y 去掉偏移,在右下角x,y加上偏移,补充这部分)
起点坐标=((画笔宽度1.41+间距)*条纹索引-偏移量,-偏移量)
终点坐标=((画笔宽度1.41+间距)*条纹索引-偏移+高度,高度+偏移)
裁剪角(如果需要)
因为画笔画的是直角,会超出背景板,需要剪掉四个角。使用
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: xxx
)
作为背景
使用Stack布局实现下面斑马纹作为背景板,上面要显示的内容
Stack(
children: [
buildZebraBack(…),
需要展示的内容
]
)
代码用在哪里 main_page.dart
Stack(
children: [
Positioned(
child: ZebraStripesBack(
width: 335,
height: 44,
lineWidth: 10,
spacing: 10,
borderRaduis: 10,
lineColor: Colors.blue),
top: 0,
left: 0,
),
Container(
width: 335,
height: 44,
alignment: Alignment.center,
padding: EdgeInsets.only(
top: 10,
left: 12,
bottom: 10,
right: 12),
child: Text(
"英语",
style: TextStyle(
color: Color(0xFFFFFFFF),
fontSize: 14.sp,
fontWeight: FontWeight.w500),
)
)
]
)
斑马条纹的具体实现类zebra_stripes_back.dart
import 'dart:math';
import 'package:flutter/material.dart';
// 斑马纹具体实现类
class ZebraStripesBack extends StatefulWidget {
ZebraStripesBack({
this.width: 0,
this.height: 0,
this.spacing: 4,
this.lineWidth: 4,
this.lineColor: Colors.transparent,
this.borderRaduis: 0,
});
final double width; // 容器宽度
final double height; // 容器高度
final double lineWidth; // 斑马纹宽度
final double spacing; // 间距
final double borderRaduis; // 容器圆角
final Color lineColor; // 斑马纹颜色
@override
State createState() => _ZebraStripesBackState();
}
class _ZebraStripesBackState extends State {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(widget.borderRaduis)),
child: CustomPaint(
size: Size(widget.width, widget.height),
painter: _ZebraStripesBackPainter(
maxWidth: widget.width,
maxHeight: widget.height,
spacing: widget.spacing,
lineWidth: widget.lineWidth,
lineColor: widget.lineColor,
borderRaduis: widget.borderRaduis,
),
));
}
}
class _ZebraStripesBackPainter extends CustomPainter {
_ZebraStripesBackPainter({
this.maxWidth: 0,
this.maxHeight: 0,
this.spacing: 4,
this.lineWidth: 4,
this.lineColor: Colors.black12,
this.borderRaduis: 0,
});
final double maxWidth;
final double maxHeight;
final double spacing;
final double lineWidth;
final Color lineColor;
final double borderRaduis;
@override
void paint(Canvas canvas, Size size) {
var paint = Paint()
..isAntiAlias = true
..style = PaintingStyle.fill
..color = lineColor
..strokeWidth = lineWidth;
int number = 0; // 个数
int fillNumber = 0; // 填充个数
double lineAndSpace = lineWidth *1.41 + spacing; // 单个条纹宽 + 间距宽
if (lineWidth > 0) {
number = (maxWidth / lineAndSpace).ceil();
fillNumber = (maxHeight / lineAndSpace).ceil(); // 填充个数
}
double deviation = lineWidth / 2.82; // x y轴偏移量 = width / 2倍根号2
for (int i = -fillNumber; i true;
}
计算过程解释偏移量计算过程
填数计算过程
为什么画笔宽度需要乘以二?
缺失填充
缺失偏移
暂无评论内容