【发布时间】:2021-02-23 05:53:44
【问题描述】:
在下面的代码中,我尝试在画布上模拟小部件。
当一个小部件/按钮被触摸时,它会在两种颜色之间翻转。
import 'package:flutter/material.dart';
void main() { runApp(MyApp()); }
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Diagram',
theme: ThemeData(
appBarTheme: AppBarTheme(color: Colors.blueAccent,),
),
home: Diagram(),
);
}
}
class Diagram extends StatefulWidget {
@override
_DiagramState createState() => new _DiagramState();
}
class _DiagramState extends State<Diagram> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Canvas Widgets'),
centerTitle: true,
),
body: Center(
child: GestureDetector(
onTapUp: (TapUpDetails details) {
setState(() {
;
});
},
child: AspectRatio(
aspectRatio: 1.0,
child: Container(
child: CustomPaint(
painter: DiagramPainter(),
),
),
),
),
),
);
}
}
class DiagramPainter extends CustomPainter {
// class DiagramPainter extends ChangeNotifier implements CustomPainter {
DiagramPainter() {
for(int i=0; i<_numberOfButtons; i++) {
state.add(false);
}
}
static final int _numberOfButtons = 3;
static final double _margin = 60;
static final double _gap = _margin / 2.0 / _numberOfButtons.toDouble();
double width;
double y;
static Canvas currentCanvas;
var buttons = [];
var state = [];
final bluePaint = Paint()
..color = Colors.blue;
final yellowPaint = Paint()
..color = Colors.yellow;
@override
void paint(Canvas canvas, Size size) {
currentCanvas = canvas;
width = (size.width - _margin) /_numberOfButtons.toDouble();
y = size.height / 2.0 - width / 2.0;
Iterable<int>.generate(_numberOfButtons).toList().forEach((index) {
buttons.add(drawButton(canvas, index));
});
}
Rect drawButton(Canvas canvas, int index) {
double left = _gap + index * (width + _gap * 2.0);
var rect = Rect.fromLTWH(left, y, width, width);
var paint = state[index] ? yellowPaint : bluePaint;
canvas.drawOval(rect, paint);
return rect;
}
@override
bool hitTest(Offset position) {
for(int i=0; i<_numberOfButtons; i++) {
if (buttons[i].contains(position)) {
state[i] = !state[i];
// trigger redraw
// notifyListeners();
return true;
}
}
return false;
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
我发现我需要class DiagramPainter extends ChangeNotifier implements CustomPainter 而不是class DiagramPainter extends CustomPainter。
我还收集到我需要通过notifyListeners() 触发重绘。在这种情况下通知谁?它仍然是DiagramPainter,不是吗?我错过了什么?
【问题讨论】:
-
要么 1) 将
Listenable传递给 CustomPainter 构造函数(通过可选的repaint命名参数)或 2)class DiagramPainter extends CustomPainter with ChangeNotifier并在需要时调用notifyListeners() -
@pskink 好吧,我实际上是在画布中寻找一组完全动态的小部件。所以 :-) 要么 1)我接受 Chunhunghan 的回答,考虑到我写当前问题的方式,这完全没问题,然后问续集;或者 2)你向我们展示了细节(魔鬼 is 在详细信息)通过写一个答案。
-
@pskink 我认为 2) 更好,因为我们可以背靠背地研究和比较这两种技术。
-
@pskink 完成了对许多代码异味的更正。不错!
-
@pskink 我在您的代码中看到了几个优点,但我仍然很难过。
ChangeNotifiermixin 的存在如何使notifyListeners()调用paint()?例如,paint()是否以某种方式声明为CustomPainter的待通知更改代理?
标签: flutter