learn-tech/专栏/Flutter入门教程/19认识自定义绘制组件.md
2024-10-16 00:01:16 +08:00

233 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

因收到Google相关通知网站将会择期关闭。相关通知内容
19 认识自定义绘制组件
1.从绘制点开始说起
我们先通过绘制点来了解一下 Flutter 中绘制的使用方式。左图中是新建的 Paper 组件作为白板主界面;右图在白板的指定坐标处绘制了四个方形的点:
空白
绘制四个点
Paper 组件如下,由于之后需要进行切换画笔颜色、粗细的操作;涉及到界面中状态的变化,所以这里继承自 StatefulWidget在状态类的 build 方法中,完成界面的构建逻辑。 PaperAppBar 是单独封装的头部标题组件,和之前类似,就不赘述了;现在主要是想让 body 处设置为可绘制的组件。
class Paper extends StatefulWidget {
const Paper({Key? key}) : super(key: key);
@override
State<Paper> createState() => _PaperState();
}
class _PaperState extends State<Paper> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PaperAppBar(onClear: _clear,),
body: //TODO
);
}
void _clear() {}
}
我们已经知道, Flutter 中的所有界面呈现,都和 Widget 息息相关,绘制也不例外。在 Flutter 中接触到 Canvas 最常用的方式是 CustomPaint 组件 + CustomPainter 画板组合。下面代码,将 body 设置为 CustomPaint 组件CustomPaint 在构造时传入 painter 参数是 CustomPainter 的子类。
自定义绘制,就是指继承 CustomPainter 完成绘制逻辑,比如这里的 PaperPainter 画板。另外,我们希望画布的尺寸填充剩余空间,可以将 child 指定为 ConstrainedBox ,并通过 BoxConstraints.expand() 的约束。
body: CustomPaint(
painter: PaperPainter(),
child: ConstrainedBox(constraints: const BoxConstraints.expand()),
),
也就是说,对于自定义绘制来说,最重要的是 CustomPainter 子类代码的实现,这里通过 PaperPainter 来完成绘制逻辑。在 paint 回调中,可以访问到 Canvas 对象和画板的尺寸 Size 。
在该方法中通过调用 Canvas 的相关方法就可以进行绘制。比如这里使用 drawPoints 绘制点集,其中需要传入三个参数,分别是:
点的模式 PointMode : 共三种模式, points、lines、polygon
点集 List<Offset> 点的坐标列表
画笔 Paint : 绘制时的配置参数
class PaperPainter extends CustomPainter{
@override
void paint(Canvas canvas, Size size) {
List<Offset> points = const [
Offset(100,100),
Offset(100,150),
Offset(150,150),
Offset(200,100),
];
Paint paint = Paint();
paint.strokeWidth = 10;
canvas.drawPoints(PointMode.points, points , paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
上面点模式是 PointMode.points 也就是绘制一个个点。如下是另外两者模式的效果看起来也很清晰PointMode.lines 会将点集分为若干对没对连接成线PointMode.polygon 会将点依次连接;
PointMode.lines
PointMode.polygon
到这里,就通过 Canvas 完成了一个最基础的点集绘制案例,当前代码位置 paper.dart 。接下来,介绍一下 Paint 对象,看看你的画笔有哪些功能。
2. 简单认识画笔的属性
可以先回想一下,我们现实中画画时用的笔有哪些特性:很自然的可以想到: 颜色、粗细 。 这两个配置项分别对应 strokeWidth 和 color 属性,在绘制之前通过直接 paint 对象设置即可:
Paint paint = Paint();
paint.strokeWidth = 10;
paint.color = Colors.red;
粗细 strokeWidth
颜色 color
之前线间的连接很突兀,可以使用将 strokeCap 设置为 StrokeCap.round 让线编程圆头:
paint.strokeCap = StrokeCap.round;
StrokeCap.butt
StrokeCap.round
这里面向新手,对于绘制的知识也点到为止,能满足当前需求即可,不会进行非常系统的介绍。不过感兴趣的可以看我的 《Flutter 绘制指南 - 妙笔生花》 小册,其中对于绘制方方面面都介绍的比较详细。
3. 简单的基础图形绘制
Canvas 中提供了一些基础图形的绘制,比如 圆形、矩形、圆角矩形、椭圆、圆弧 等,这里简单了解一下。
drawCircle 绘制圆形: 三个入参分别是圆心坐标 Offset、半径 double 、 画笔 Paint。
另外Paint 默认是填充样式,如下左图会填满内部;可以将 style 设置为 PaintingStyle.stroke变成线型模式如下右图
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
canvas.drawCircle(Offset(100, 100), 50, paint);
paint.style = PaintingStyle.stroke;
canvas.drawCircle(Offset(250, 100), 50, paint);
}
drawRect 绘制矩形:两个入参分别是矩形 Rect、画笔 Paint。
drawRRect 绘制圆角矩形:两个入参分别是矩形 RRect、画笔 Paint。
Paint paint = Paint();
paint.style = PaintingStyle.stroke;
paint.strokeWidth = 2;
// 绘制矩形
Rect rect = Rect.fromCenter(center: Offset(100, 100), width: 100, height: 80);
canvas.drawRect(rect, paint);
// 绘制圆角矩形
paint.style = PaintingStyle.fill;
RRect rrect = RRect.fromRectXY(rect.translate(150, 0), 8, 8);
canvas.drawRRect(rrect, paint);
drawOval 绘制椭圆:两个入参分别是矩形 Rect、画笔 Paint。
drawArc 绘制圆弧:五个入参分别是矩形 RRect、起始弧度 double、扫描弧度 double、是否闭合 bool、画笔 Paint。
Paint paint = Paint();
paint.strokeWidth = 2;
// 绘制椭圆
Rect overRect = Rect.fromCenter(center: Offset(100, 100), width: 100, height: 80);
canvas.drawOval(overRect, paint);
// 绘制圆弧
canvas.drawArc(overRect.translate(150, 0), 0, pi*1.3,true,paint);
4. 本章小结
本章主要介绍了如果在 Flutter 中通过 Canvas 自定义绘制内容。界面就相当于一张白纸、绘制接口方法就相当于画笔,使用已经存在的组件固然简单,但学会自己控制画笔绘制内容可以创造更多的精彩。当然,想要精通绘制也不是一朝一夕可以达成的,但凡工艺技能,都是熟能生巧。
这里只是简单认识了在 Flutter 中使用 Canvas 绘制的方式,接下来将结合手势和绘制,完成在手指在界面上拖拽留下痕迹的绘制效果。