import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'dart:ui'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Stiletto', theme: ThemeData( primarySwatch: Colors.red, ), home: Scaffold( appBar: AppBar( title: Text("Stiletto"), ), body: Center( child: SizedBox.expand( child: StilettoCanvas() ) ) ) ); } } class StilettoCanvas extends StatefulWidget { StilettoCanvas({Key? key}) : super(key: key); @override _StilettoCanvasState createState() => _StilettoCanvasState(); } class _StilettoCanvasState extends State { List _currentPath = []; bool _isDrawing = false; RenderBox? _currentRenderBox = null; final GlobalKey _globalKey = GlobalKey(); _afterLayout(Duration) { RenderObject? renderObject = _globalKey.currentContext?.findRenderObject(); if (renderObject is RenderBox) { _currentRenderBox = renderObject; } } void _onPointerDown(PointerDownEvent event) { setState(() { _currentPath = []; _isDrawing = true; }); } void _onPointerUp(PointerUpEvent event) { setState(() { _currentPath = []; _isDrawing = false; }); } void _onPointerMove(PointerMoveEvent event) { setState(() { Offset? localMousePos = _currentRenderBox?.globalToLocal(event.position); if (localMousePos is Offset) { _currentPath.add(localMousePos); } }); } @override Widget build(BuildContext context) { WidgetsBinding.instance?.addPostFrameCallback(_afterLayout); return Listener( onPointerDown: _onPointerDown, onPointerUp: _onPointerUp, onPointerMove: _onPointerMove, child: ClipRect( child: CustomPaint( painter: StilettoPainter(_currentPath, _isDrawing), ), key: _globalKey ) ); } } class StilettoPainter extends CustomPainter { StilettoPainter(this.currentPath, this.isDrawing) : super(); final List currentPath; final bool isDrawing; @override void paint(Canvas canvas, Size size) { final Rect rect = Offset.zero & size; canvas.drawRect( rect, Paint()..color = Color(0xFFFFFFFF) ); final strokePaint = Paint() ..color = Colors.black ..strokeWidth = 1.0; canvas.drawPoints(PointMode.polygon, currentPath, strokePaint); } @override bool shouldRepaint(StilettoPainter oldDelegate) { return currentPath != oldDelegate.currentPath || isDrawing; } }