Итак, я пытаюсь создать приложение для рисования, используя Flutter, следуя методу «signature canvas». Однако у меня возникли проблемы с возможностью изменить цвет объекта CustomPaint без изменения цветов для каждой линии перед изменением, как показано здесь:
![enter image description here](https://i.stack.imgur.com/9k75M.gif)
Как вы можете видеть, изменение цвета происходит после изменения состояния виджета страницы (либо щелкая по основному FAB, либо, если бы я снова рисовал на холсте). Вот мой код ниже для моей DrawPage:
class DrawPage extends StatefulWidget {
@override
DrawPageState createState() => new DrawPageState();
}
class DrawPageState extends State<DrawPage> with TickerProviderStateMixin {
AnimationController controller;
List<Offset> points = <Offset>[];
Color color = Colors.black;
StrokeCap strokeCap = StrokeCap.round;
double strokeWidth = 5.0;
@override
void initState() {
super.initState();
controller = new AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: GestureDetector(
onPanUpdate: (DragUpdateDetails details) {
setState(() {
RenderBox object = context.findRenderObject();
Offset localPosition =
object.globalToLocal(details.globalPosition);
points = new List.from(points);
points.add(localPosition);
});
},
onPanEnd: (DragEndDetails details) => points.add(null),
child: CustomPaint(
painter: Painter(
points: points,
color: color,
strokeCap: strokeCap,
strokeWidth: strokeWidth),
size: Size.infinite,
),
),
),
floatingActionButton:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Container(
height: 70.0,
width: 56.0,
alignment: FractionalOffset.topCenter,
child: ScaleTransition(
scale: CurvedAnimation(
parent: controller,
curve: Interval(0.0, 1.0 - 0 / 3 / 2.0, curve: Curves.easeOut),
),
child: FloatingActionButton(
mini: true,
child: Icon(Icons.clear),
onPressed: () {
points.clear();
},
),
),
),
Container(
height: 70.0,
width: 56.0,
alignment: FractionalOffset.topCenter,
child: ScaleTransition(
scale: CurvedAnimation(
parent: controller,
curve: Interval(0.0, 1.0 - 1 / 3 / 2.0, curve: Curves.easeOut),
),
child: FloatingActionButton(
mini: true,
child: Icon(Icons.lens),
onPressed: () {},
),
),
),
Container(
height: 70.0,
width: 56.0,
alignment: FractionalOffset.topCenter,
child: ScaleTransition(
scale: CurvedAnimation(
parent: controller,
curve:
Interval(0.0, 1.0 - 2 / 3 / 2.0, curve: Curves.easeOut),
),
child: FloatingActionButton(
mini: true,
child: Icon(Icons.color_lens),
onPressed: () async {
Color temp;
temp = await showDialog(
context: context,
builder: (context) => ColorDialog());
if (temp != null) {
setState(() {
color = temp;
});
}
}))),
FloatingActionButton(
child: AnimatedBuilder(
animation: controller,
builder: (BuildContext context, Widget child) {
return Transform(
transform: Matrix4.rotationZ(controller.value * 0.5 * math.pi),
alignment: FractionalOffset.center,
child: Icon(Icons.brush),
);
},
),
onPressed: () {
if (controller.isDismissed) {
controller.forward();
} else {
controller.reverse();
}
},
),
]),
);
}
}
Что я пробовал до сих пор:
Я пытался поиграть с тем, как точки добавляются в мой список смещений, так как этот список воссоздается после каждого жеста «рисования», такого как простое добавление в текущий список без его воссоздания, но это нарушает жест «рисования». :
setState(() {
RenderBox object = context.findRenderObject();
Offset localPosition =
object.globalToLocal(details.globalPosition);
points = new List.from(points);
points.add(localPosition);
});
Я пытался сделать ссылку на объект CustomPaint или мой объект Painter вне области действия build () и таким образом обновить свойство color, но это также нарушает жест "рисования".
Любая помощь будет принята с благодарностью!
Кроме того, вот код для моего класса Painter на случай, если люди захотят его увидеть:
class Painter extends CustomPainter {
List<Offset> points;
Color color;
StrokeCap strokeCap;
double strokeWidth;
Painter({this.points, this.color, this.strokeCap, this.strokeWidth});
@override
void paint(Canvas canvas, Size size) {
Paint paint = new Paint();
paint.color = color;
paint.strokeCap = strokeCap;
paint.strokeWidth = strokeWidth;
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);
}
}
}
@override
bool shouldRepaint(Painter oldPainter) => oldPainter.points != points;
}