因此,我尝试按照“签名画布”方法使用Flutter创建绘图应用程序。但是,我无法更改CustomPaint对象的颜色,而不必在更改之前更改每个线条绘制的颜色,如下所示:
如您所见,一旦页面小部件的状态改变(通过单击主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);
});
我尝试在build()范围之外引用CustomPaint对象或我的Painter对象,并以此方式更新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;
}
答案 0 :(得分:1)
我认为,对于不同的颜色,您必须使用不同的涂料。我已经对您的代码进行了一些小的更改,即可使用。
class DrawPageState extends State<DrawPage> with TickerProviderStateMixin {
...
List<Painter> painterList = [];
@override
Widget build(BuildContext context) {
...
child: CustomPaint(
painter: Painter(
points: points, color: color, strokeCap: strokeCap, strokeWidth: strokeWidth, painters: painterList),
size: Size.infinite,
),
...
onPressed: () async {
Color temp;
temp = await showDialog(
context: context,
builder: (context) => ColorDialog());
if (temp != null) {
setState(() {
painterList
.add(Painter(points: points.toList(), color: color, strokeCap: strokeCap, strokeWidth: strokeWidth));
points.clear();
strokeCap = StrokeCap.round;
strokeWidth = 5.0;
color = temp;
});
}
...
}
}
class Painter extends CustomPainter {
List<Offset> points;
Color color;
StrokeCap strokeCap;
double strokeWidth;
List<Painter> painters;
Painter({this.points, this.color, this.strokeCap, this.strokeWidth, this.painters = const []});
@override
void paint(Canvas canvas, Size size) {
for (Painter painter in painters) {
painter.paint(canvas, size);
}
Paint paint = new Paint()
..color = color
..strokeCap = strokeCap
..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 oldDelegate) => oldDelegate.points != points;
}
答案 1 :(得分:0)
2020年,我对此有一个不错的解决方案,因为实际选择的方案对我不起作用,并且我看到一些多余的电话。
因此,我开始创建一个小类:
class _GroupPoints {
Offset offset;
Color color;
_GroupPoints({this.offset, this.color});
}
接下来,我这样声明我的CustomPainter
:
class Signature extends CustomPainter {
List<_GroupPoints> points;
Color color;
Signature({
this.color,
this.points,
});
@override
void paint(Canvas canvas, Size size) {
Paint paint = new Paint()
// if you need this next params as dynamic, you can move it inside the for part
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
for (int i = 0; i < newPoints.length - 1; i++) {
paint.color = points[i].color;
if (points[i].offset != null && points[i + 1].offset != null) {
canvas.drawLine(points[i].offset, points[i + 1].offset, paint);
}
canvas.clipRect(Offset.zero & size);
}
}
@override
bool shouldRepaint(Signature oldDelegate) => true;
}
在我的小部件上:
...
class _MyPageState extends State<MyPage> {
...
List<_GroupPoints> points = [];
...
Container(
height: 500,
width: double.infinity,
child: GestureDetector(
onPanUpdate: (DragUpdateDetails details) {
setState(() {
points = new List.from(points)
..add(
new _GroupPoints(
offset: details.localPosition,
color: myDynamicColor,
),
);
});
},
onPanEnd: (DragEndDetails details) {
points.add(
_GroupPoints(
color: myDynamicColor,
offset: null),
);
},
child: CustomPaint(
painter: Signature(
newPoints: points,
color: myDynamicColor,
),
),
),
),
}
通过这种方式,我们可以使用具有各自颜色的多个点绘制。希望这可以帮助任何人。