根据CustomPainter
docs,您必须在需要重绘时通知油漆小部件
触发重画的最有效方法是扩展此类并向CustomPainter的构造函数提供重画参数,该对象在需要重画时通知其侦听器,或扩展Listenable(例如,通过ChangeNotifier)并实现CustomPainter,以便对象本身直接提供通知。在这两种情况下,无论何时勾选动画,CustomPaint小部件或RenderCustomPaint渲染对象都将侦听Listenable并重新绘制,从而避免了管道的构建和布局阶段。
例如,
KanjiPainter应该扩展
ChangeNotifier并实施
CustomPainter。当您更改笔触时,
notifyListeners
并且
build函数总是创建new
KanjiPainter,这将删除所有旧数据。您可以
initState一次启动画家。
工作示例:
class WriteScreen extends StatefulWidget { @override _WriteScreenState createState() => new _WriteScreenState();}class KanjiPainter extends ChangeNotifier implements CustomPainter { Color strokeColor; var strokes = new List<List<Offset>>(); KanjiPainter(this.strokeColor); bool hitTest(Offset position) => null; void startStroke(Offset position) { print("startStroke"); strokes.add([position]); notifyListeners(); } void appendStroke(Offset position) { print("appendStroke"); var stroke = strokes.last; stroke.add(position); notifyListeners(); } void endStroke() { notifyListeners(); } @override void paint(Canvas canvas, Size size) { print("paint!"); var rect = Offset.zero & size; Paint fillPaint = new Paint(); fillPaint.color = Colors.yellow[100]; fillPaint.style = PaintingStyle.fill; canvas.drawRect(rect, fillPaint); Paint strokePaint = new Paint(); strokePaint.color = Colors.black; strokePaint.style = PaintingStyle.stroke; for (var stroke in strokes) { Path strokePath = new Path(); // Iterator strokeIt = stroke.iterator..moveNext(); // Offset start = strokeIt.current; // strokePath.moveTo(start.dx, start.dy); // while (strokeIt.moveNext()) { // Offset off = strokeIt.current; // strokePath.addP // } strokePath.addPolygon(stroke, false); canvas.drawPath(strokePath, strokePaint); } } bool shouldRepaint(covariant CustomPainter oldDelegate) { return true; }}class _WriteScreenState extends State<WriteScreen> { GestureDetector touch; CustomPaint canvas; KanjiPainter kanjiPainter; void panStart(DragStartDetails details) { print(details.globalPosition); kanjiPainter.startStroke(details.globalPosition); } void panUpdate(DragUpdateDetails details) { print(details.globalPosition); kanjiPainter.appendStroke(details.globalPosition); } void panEnd(DragEndDetails details) { kanjiPainter.endStroke(); } @override void initState() { super.initState(); kanjiPainter = new KanjiPainter(const Color.fromRGBO(255, 255, 255, 1.0)); } @override Widget build(BuildContext context) { touch = new GestureDetector( onPanStart: panStart, onPanUpdate: panUpdate, onPanEnd: panEnd, ); canvas = new CustomPaint( painter: kanjiPainter, child: touch, // child: new Text("Custom Painter"), // size: const Size.square(100.0), ); Container container = new Container( padding: new EdgeInsets.all(20.0), child: new ConstrainedBox( constraints: const BoxConstraints.expand(), child: new Card( elevation: 10.0, child: canvas, ))); return new Scaffold( appBar: new AppBar(title: new Text("Draw!")), backgroundColor: const Color.fromRGBO(200, 200, 200, 1.0), body: container, ); }}


