class _MyHomePageState extends State<MyHomePage>{ static List<Offset> _points = []; @override void initState(){ super.initState(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color.fromARGB(255, 255,255,255), appBar: AppBar( title: Text('App Name', style: TextStyle(fontSize: 30.0),), ), body: Center( child: Listener( onPointerDown: _addPoint, child: CustomPaint( painter: MyPainter(_points), child: Center(), ), ), ) ); } void _addPoint(PointerDownEvent event) { setState((){ _points.add(event.localPosition); }); } } class MyPainter extends CustomPainter { final List<Offset> _points; MyPainter(this._points); @override void paint(Canvas canvas, Size size){ Paint p = Paint(); p.style = PaintingStyle.fill; p.color = Color.fromARGB(100, 0, 200, 100); for(var pos in _points) { Rect r = Rect.fromLTWH(pos.dx - 25, pos.dy - 25, 50.0, 50.0); canvas.drawOval(r, p); } } @override bool shouldRepaint(CustomPainter oldDelegate) => true; }
UIウィジェットで操作
class _MyHomePageState extends State<MyHomePage>{ static double _value = 0; static double _opaq = 0; @override void initState(){ super.initState(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color.fromARGB(255, 255,255,255), appBar: AppBar( title: Text('App Name', style: TextStyle(fontSize: 30.0),), ), body: Column( children: [ Padding(padding: EdgeInsets.all(10)), Container( width: 300, height: 300, child: CustomPaint( painter: MyPainter(_value, _opaq.toInt()), child: Center(), ), ), Slider( min: 0.0, max: 300.0, value:_value, onChanged: _changeVal, ), Slider( min:0.0, max:255.0, value:_opaq, onChanged: _changeOpaq, ), ], ), ); } void _changeVal(double value) { setState((){ _value = value; }); } void _changeOpaq(double value) { setState((){ _opaq = value; }); } } class MyPainter extends CustomPainter { final double _value; final int _opaq; MyPainter(this._value, this._opaq); @override void paint(Canvas canvas, Size size){ Paint p = Paint(); p.style = PaintingStyle.fill; p.color = Color.fromARGB(_opaq, 0, 200, 100); Rect r = Rect.fromLTWH( (size.width - _value) / 2, (size.height - _value) / 2, _value, _value); canvas.drawOval(r, p); r = Rect.fromLTWH(0, 0, size.width, size.height); p.style = PaintingStyle.stroke; p.color = Color.fromARGB(255, 100, 100, 100); canvas.drawRect(r, p); } @override bool shouldRepaint(CustomPainter oldDelegate) => true; }
ValueNotifierによる更新
class _MyHomePageState extends State<MyHomePage>{ static ValueNotifier<int> _value = ValueNotifier<int>(0); @override void initState(){ super.initState(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color.fromARGB(255, 255,255,255), appBar: AppBar( title: Text('App Name', style: TextStyle(fontSize: 30.0),), ), body: Center( child:Column( children: [ Padding(padding: EdgeInsets.all(10)), Container( width: 300, height: 300, child: CustomPaint( painter: MyPainter(_value), child: Center(), ), ), Padding(padding: EdgeInsets.all(5)), ElevatedButton( child: Text("Click", style: TextStyle(fontSize: 32),), onPressed: ()=> _value.value++, ), ], ), ), ); } } class MyPainter extends CustomPainter { final ValueNotifier<int> _value; MyPainter(this._value); @override void paint(Canvas canvas, Size size){ Paint p = Paint(); p.style = PaintingStyle.fill; p.color = Color.fromARGB(50, 0, 255, 255); Rect r; for (var i = 0 ; i < _value.value; i++){ r = Rect.fromLTWH(10+i*20, 10+i*20, 100, 100); canvas.drawRect(r, p); } r = Rect.fromLTWH(0, 0, size.width, size.height); p.style = PaintingStyle.stroke; p.color = Color.fromARGB(255, 100, 100, 100); canvas.drawRect(r, p); if (_value.value > 10) _value.value = 0; } @override bool shouldRepaint(CustomPainter oldDelegate) => true; }