Im trying to design a simple drawing app in flutter and I'm having trouble trying to implement the actual brush strokes and how they look. Here is my code:
import 'package:flutter/material.dart';
import 'components/paint_selector.dart';
import 'components/paint_list.dart' as paintList;
import 'components/user_canvas.dart';
import 'components/objects/userLine.dart';
//boilderplate code
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// GlobalKey _key = GlobalKey();
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AGG Demo',
// theme: ThemeData(
// primarySwatch: Colors.blue,
// ),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
Paint globalBrush = Paint()
..color = Colors.black
..strokeWidth = 5;
UserLine strokePath = UserLine();
@override
Widget build(BuildContext context) {
List<Paint> paintList = [
Paint()
..color = Colors.red,
Paint()
..color = Colors.green,
Paint()
..color = Colors.blue,
];
double screenHeight = MediaQuery.of(context).size.height;
double screenWidth = MediaQuery.of(context).size.width;
return Container(
height: screenHeight,
width: screenWidth,
color: Colors.black,
child: GestureDetector(
onPanStart: (details) {
strokePath = UserLine();
strokePath.points.add(details.localPosition);
},
onPanUpdate: (details) {
strokePath.points.add(details.localPosition);
print("localPosition = ${details.localPosition}");
print("globalPosition = ${details.globalPosition}");
},
onPanEnd: (details) {
//dont think we need to do anthing here yet!
},
child: CustomPaint(
painter: UserCanvas(globalBrush, strokePath),
child: PaintSelector(
globalBrush: globalBrush,
paintList: paintList,
),
),
),
);
}
}
Im not sure if my brushstrokes are working, but they're just invisible or if I'm messing up somewhere along the way. It might have something to do with another one of my widgets covering the canvas, because when I change the color of that one, the whole screen changes to the color of it aswell. Code:
import 'package:flutter/material.dart';
class PaintSelector extends StatefulWidget {
final Paint globalBrush; // the brush the canvas uses - is changed when the user selects a new color
final List<Paint>? paintList; // the list of paints that the user can choose from
const PaintSelector({Key? key, required this.globalBrush, this.paintList}) : super(key: key);
@override
State<PaintSelector> createState() => _PaintSelectorState();
}
class _PaintSelectorState extends State<PaintSelector> {
@override
Widget build(BuildContext context) {
return Container(
width: 20,
height: 20,
alignment: Alignment.topRight,
color: Colors.black,
padding: const EdgeInsets.only(top: 40),
child: Column(
children: [
for (var paint in widget.paintList!)
colorButton(
paint: paint,
globalBrush: widget.globalBrush,
),
]
),
);
}
}
class colorButton extends StatefulWidget {
final Paint paint; // the individual paint that can be customized by the user eventually
Paint globalBrush; //the brush the canvas is uses - is changed when the user selects a new color
colorButton({super.key, required this.paint, required this.globalBrush});
@override
State<colorButton> createState() => _colorButtonState();
}
class _colorButtonState extends State<colorButton> {
bool isSelected = false;
double borderWidth = 1;
@override
Widget build(BuildContext context) {
Color color = widget.paint.color;
return GestureDetector(
onTap: () {
setState(() {
widget.globalBrush = widget.paint;
print("selected color = $color");
});
},
onTapDown: (details) {
setState(() {
borderWidth = 4;
});
},
onTapUp: (details) {
setState(() {
borderWidth = 1;
});
},
child: Container(
height: 50,
width: 50,
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: color,
border: Border.all(
color: Colors.white,
width: borderWidth,
),
),
),
);
}
}
A couple of things.
PaintSelectoron top of yourCustomPaintwidgetcolorButtonwidget, you are trying to change theglobalBrushdirectly. This will not reflect in the parent widget. Instead, you should use a callback function to notify the parent widget about the color change.Some code change:
Make
MyHomePagea stateful widget and add the below:Most of the code remains same up until the child of the Container in MyHomePage.The child should be a stack as shown below:
We have added a callback for onBrushChanged to update the globalBrush. We modify PaintSelector to use this callback as shown below:
We also modify
colorButton. its better you name itColorButton(naming convention).Hopefully this helps or provides you with some insight.