[英]Changing colour of CustomPaint changes for all previous points
所以我試圖按照“簽名畫布”方法使用 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 對象並以這種方式更新顏色屬性,但這也會破壞“繪制”手勢。
任何幫助將不勝感激!
另外,這是我的 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;
}
我認為,對於不同的顏色,您必須使用不同的油漆。 我對您的代碼進行了一些小的更改,它有效。
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;
}
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,
),
),
),
),
}
通過這種方式,我們可以使用具有各自顏色的多個點繪制。 希望這可以幫助任何人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.