Почему «points.clear» и «points.add» (точки - это список смещения) не работают одинаково в 10-й пробной версии CustomPaint во Flutter?
Он работает для некоторых испытаний, затем не работает для некоторых испытаний, а затем снова работает (без какого-либо конкретного шаблона). Я имею в виду, например, что он исправляет линию и рисует идеальную линию 3-4 раза, используя только первую и последнюю точку, а затем на один раз он покидает линию, которую нарисовал пользователь. Кажется, что
points.clear
или же
points.add
иногда работает, а иногда нет. Я знаю, это звучит глупо, но я не могу объяснить это логически. Я был бы очень благодарен, если бы кто-нибудь мог взглянуть на код и рассказать мне, что происходит.
вот мой GestureDetector:
body: GestureDetector(
onPanDown: (DragDownDetails details) {
setState(() {
points.clear();
});
},
onPanUpdate: (DragUpdateDetails details) {
//when the user touch the screen and move
setState(() {
RenderBox box = context.findRenderObject(); //finds the scaffold
Offset point = box.globalToLocal(details.globalPosition);
point = point.translate(0.0, -(AppBar().preferredSize.height + 30));
points = List.from(points)
..add(point); //add the points when user drag in screen
firstPoint = points.first; //storing the first point for drawing the line
});
},
onPanEnd: (DragEndDetails details) {
setState(() {
if (mode == "Line") {
Offset lastPoint = points.last; //storing the last point for drawing the line
points.clear();
points.add(firstPoint);
points.add(lastPoint);
points.add(null);
}
});
},
child: sketchArea,
),
и вот мой класс CustomPainter:
class Sketcher2 extends CustomPainter {
final List<Offset> points;
Sketcher2(this.points);
@override
bool shouldRepaint(Sketcher2 oldDelegate) {
return oldDelegate.points != points;
}
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = Colors.black //seting the color of the drawing
..strokeCap = StrokeCap.round //the shape of a single dot (single touch)
..strokeWidth = 4.0; // the width of a single dot (single touch)
for (int i = 0; i < points.length - 1; i++) {
if (points[i] != null && points[i + 1] != null) {
canvas.drawLine(points[i], points[i + 1], paint);
}
}
}
}
2 ответа
У вас может быть проблема с
shouldRepaint
вашей
Sketcher2
:
@override
bool shouldRepaint(Sketcher2 oldDelegate) {
return oldDelegate.points != points;
}
В
!=
оператор сравнивает объекты. Он вернет истину тогда и только тогда, когда
oldDelegate.points
и не являются одним и тем же объектом.
На самом деле, я очень удивлен, что это когда-либо работает. Я пробовал ваш исходный код, и он никогда не работает на моей стороне.
1. Быстрое решение
В
onPanEnd
вместо того, чтобы очищать точки, повторно инициализируйте список на новый
[]
:
onPanEnd: (DragEndDetails details) {
setState(() {
if (mode == "Line") {
Offset lastPoint = points.last;
points = []; // instead of points.clear();
points.add(firstPoint);
points.add(lastPoint);
points.add(null);
} else if (mode == "FreeDraw") {
points.add(null);
}
});
},
Кстати, вы сделали это правильно, используя копию списка с
points = List.from(points)..add(point);
.
2. Дальнейшие упрощения
Вы можете немного упростить свой GestureDetector.
- Ты
firstPoint
являетсяpoints.first
, нет необходимости хранить для этого отдельную переменную; - То же самое для твоего
lastPoints
; - В
details
изonPanUpdate
уже дал вамlocalPosition
; - Почему вы добавляете
null
в концеpoints
?
Ваш
Page
становится:
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<Offset> points = <Offset>[];
String mode = 'Line';
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onPanDown: (DragDownDetails details) => setState(() => points = []),
onPanUpdate: (DragUpdateDetails details) =>
setState(() => points = [...points, details.localPosition]),
onPanEnd: (DragEndDetails details) => setState(() {
if (mode == "Line") points = [points.first, points.last];
}),
child: SketchArea(points: points),
),
);
}
}
Я просто изменил эту часть:
points.add(firstPoint);
points.add(lastPoint);
к
points = List.from(points)..add(firstPoint);
points = List.from(points)..add(lastPoint);
и моя проблема решена.