盛年不重来,一日难再晨。及时宜自勉,岁月不待人。——陶渊明
最近着手用Flutter开发一个项目,以前因为有原生开发的经验,所以上手比较快。
应用开发的过程中不仅仅是编码,还需要和UI小姐姐的配合,才能完成界面。如果要求我们手动去绘制一些圆形啊、线条啊、多边形呀;这时就比较考验你的耐心和基本功了。
看看UI给开发的设计图,因为没有提供虚线切图,这时需要我们手动去实现一下了,不辛苦,马上就好。
➊ 多个Container 相邻拼凑,设置间距,同时和Colum\Row搭配,实现竖线或水平线
➋ 可以绘制一条水平的虚线,然后做一个旋转90度,这样不就是一条竖直的虚线了吗
➌ 第三种方案就是我们今天要说的CustomPaint+画布(Canvas) 进行实现
有人也许会疑惑,方案1和方案二不都是采用的绘制吗,那可不一定。有的时候解决问题,我们不遵循常规也可以解决问题,满足一时之需了。
1、解决问题奇葩方式一:
为什么奇葩呢?我们采用多个Container进行竖直或者水平排列完成了效果,至于性能上我们后面慢慢验证了。
_lineContainer() {
return Container(
margin: EdgeInsets.only(top: 2.0),
color: Colors.blue,
height: 8.0,
width: 2.0,
);
}
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white,
padding: EdgeInsets.only(top: 100.0),
child: Column(
children: [
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
],
),
);
}
效果图:
不同宽度的虚线只需要修改属性width,达到效果。
水平虚线实现:
效果图:
2、解决问题奇葩方式二:
多个Containter相邻而且相同间距拼凑成水平线,然后进行一个旋转:
_lineContainer() {
return Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(left: 2.0),
color: Colors.green,
height: 2.0,
width: 8.0,
);
}
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white,
alignment: Alignment.topLeft,
padding: EdgeInsets.only(top: 300.0),
child: DecoratedBox(
decoration: BoxDecoration(color: Colors.transparent),
child: Transform.rotate(
//旋转90度
angle: math.pi / 2,
child: Row(
children: [
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
_lineContainer(),
],
),
),
),
);
}
效果如下:
3、今天主要提及的CustomPaint+画布(Canvas)
涉及的几个点:画笔(Paint)、样式(PaintingStyle)、color(颜色)、线条宽度(strokeWidth);
offset(第一参数,第二参数):表示第一参数和第二参数之间的偏移量。
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
var paint = Paint()
..isAntiAlias = true
..style = PaintingStyle.fill //填充
..color = Color(0x77cdb175); //背景为纸黄色
canvas.drawRect(Offset.zero & size, paint);
paint
..style = PaintingStyle.stroke //线
..color = Colors.red
..strokeWidth = 1.0;
for (int i = 0; i <= 35; ++i) {
double dx = 6.0 * i;
canvas.drawLine(Offset(dx, 20), Offset(dx, 22), paint);
}
}
//在实际场景中正确利用此回调可以避免重绘开销,本示例我们简单的返回true
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
引用自定义绘画:
@override
Widget build(BuildContext context) {
return Container(color: Colors.white,child :Center(
child: CustomPaint(
size: Size(300, 300), //指定画布大小
painter: MyPainter(),
),
));
}
效果渐渐离我们很近了:
往后多余的时间,我会对不同画虚线的方式优缺点做对比。
总结:
不管我们用什么方式绘制虚线,都可以达到同样的效果;虽然有的方式很繁琐,但是在解决问题的时候可以认为它不是最佳选择。努力去尝试,尽量以Flutter官网作为参考,这样才不会违背开发的原则。
参考:自绘组件 (CustomPaint与Canvas)https://book.flutterchina.club/chapter10/custom_paint.html
container:https://book.flutterchina.club/chapter5/container.html?h=Container
变换(transform):https://book.flutterchina.club/chapter5/transform.html?h=%E6%97%8B%E8%BD%AC