我正在研究要在我的应用程序中使用的绘图功能。我尝试按照这个答案来实现橡皮擦功能。它工作正常,但我面临的问题是,当我再次选择钢笔工具绘制点时,使用橡皮擦工具擦除绘制的点后,它不会在已擦除的区域上绘制。例如:
- 我用手指在屏幕上绘图(启用钢笔工具)
- 我用手指擦除屏幕上的绘制区域(启用橡皮擦工具)
- 我再次选择钢笔工具并用手指在屏幕上绘制,但这不会在已擦除区域上绘制点。有什么办法可以解决这个问题?
这是我到目前为止实现的代码:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
enum Tool { PEN, ERASER }
class DrawingData {
Offset point;
Paint paint;
DrawingData({this.point, this.paint});
}
class MyDrawing extends StatefulWidget {
@override
_MyDrawingState createState() => _MyDrawingState();
}
class _MyDrawingState extends State<MyDrawing> {
List<DrawingData> penPoints = [];
List<DrawingData> eraserPoints = [];
Color selectedColor;
double strokeWidth;
Tool tool = Tool.PEN;
@override
void initState() {
super.initState();
selectedColor = Colors.black;
strokeWidth = 5.0;
SystemChrome.setEnabledSystemUIOverlays([]);
}
void selectColor() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Select a color'),
content: SingleChildScrollView(
child: BlockPicker(
pickerColor: selectedColor,
onColorChanged: (color) {
this.setState(() {
selectedColor = color;
});
},
),
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('Close'),
),
],
);
},
);
}
void _addPenPoints(details) {
setState(() {
penPoints.add(DrawingData(
point: details.localPosition,
paint: Paint()
..strokeCap = StrokeCap.round
..isAntiAlias = true
..color = selectedColor
..strokeWidth = strokeWidth
..blendMode = BlendMode.color));
});
}
void _addEraserPoints(details) {
setState(() {
eraserPoints.add(DrawingData(
point: details.localPosition,
paint: Paint()
..strokeCap = StrokeCap.round
..isAntiAlias = true
..color = selectedColor
..strokeWidth = strokeWidth
..blendMode = BlendMode.clear));
});
}
@override
Widget build(BuildContext context) {
final double width = MediaQuery.of(context).size.width;
final double height = MediaQuery.of(context).size.height;
Widget drawingArea = Center(
child: Container(
width: width,
height: height,
child: GestureDetector(
onPanDown: tool == Tool.PEN ? _addPenPoints : _addEraserPoints,
onPanUpdate: tool == Tool.PEN ? _addPenPoints : _addEraserPoints,
onPanEnd: tool == Tool.PEN
? (details) {
setState(() {
penPoints.add(null);
});
}
: (details) {
setState(() {
eraserPoints.add(null);
});
},
child: CustomPaint(
painter: MyCustomPainter(
penPoints: penPoints,
eraserPoints: eraserPoints,
tool: tool,
),
),
),
),
);
Widget drawingSettings = Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(11.0)),
),
child: Row(
children: [
IconButton(
icon: Icon(
Icons.brush,
color: tool == Tool.PEN ? selectedColor : Colors.black,
),
onPressed: () {
setState(() {
tool = Tool.PEN;
});
},
),
IconButton(
icon: Icon(
Icons.color_lens,
color: selectedColor,
),
onPressed: () {
selectColor();
},
),
Slider(
min: 1.0,
max: 11.0,
label: "Stroke $strokeWidth",
activeColor: selectedColor,
value: strokeWidth,
onChanged: (value) {
setState(() {
strokeWidth = value;
});
},
),
IconButton(
icon: Icon(
Icons.remove_circle,
color: tool == Tool.ERASER ? selectedColor : Colors.black,
),
onPressed: () {
setState(() {
tool = Tool.ERASER;
});
},
),
IconButton(
icon: Icon(
Icons.layers_clear,
color: Colors.black,
),
onPressed: () {
setState(() {
penPoints.clear();
eraserPoints.clear();
});
},
),
],
),
),
],
),
],
);
return Stack(
children: [
drawingArea,
drawingSettings,
],
);
}
}
class MyCustomPainter extends CustomPainter {
List<DrawingData> penPoints;
List<DrawingData> eraserPoints;
Tool tool;
MyCustomPainter(
{@required this.penPoints,
@required this.eraserPoints,
@required this.tool});
@override
void paint(Canvas canvas, Size size) {
canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());
for (int x = 0; x < penPoints.length - 1; x++) {
if (penPoints[x] != null && penPoints[x + 1] != null) {
canvas.drawLine(
penPoints[x].point, penPoints[x + 1].point, penPoints[x].paint);
} else if (penPoints[x] != null && penPoints[x + 1] == null) {
canvas.drawPoints(
PointMode.points, [penPoints[x].point], penPoints[x].paint);
}
}
for (int x = 0; x < eraserPoints.length - 1; x++) {
if (eraserPoints[x] != null && eraserPoints[x + 1] != null) {
canvas.drawLine(eraserPoints[x].point, eraserPoints[x + 1].point,
eraserPoints[x].paint);
} else if (eraserPoints[x] != null && eraserPoints[x + 1] == null) {
canvas.drawPoints(
PointMode.points, [eraserPoints[x].point], eraserPoints[x].paint);
}
}
canvas.restore();
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}