我必须实现一个自定义的模拟时钟,其中时针指示早餐,午餐和晚餐时间,并且用户可以通过旋转指针来重置时间。我能够借助canvas和CustomPaint绘制时钟和指针,并且已经堆叠在Stack Widget中。我为每只指针添加了GestureDetector,并且使用onPan事件也能够旋转指针。但是问题是当多只指针放在堆栈中,只有最后添加的时钟指针正在移动,而其他指针没有检测到该手势。如何将事件传递到堆栈中,以便所有手势检测器都能检测到该指针?
用于绘制钟针
class ClockHandComponent extends StatefulWidget {
final String title;
final int time;
final Color color;
const ClockHandComponent({Key key, this.title, this.time, this.color})
: super(key: key);
@override
ClockHandComponentState createState() {
return new ClockHandComponentState();
}
}
class ClockHandComponentState extends State<ClockHandComponent> {
int time;
double angle;
ClockHandPainter _clockHandPainter;
@override
void initState() {
time = widget.time;
angle = 2 * pi / 24 * time;
initialize();
super.initState();
}
@override
void didUpdateWidget(ClockHandComponent oldWidget) {
initialize();
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanDown: _onPanDown,
onPanUpdate: _onPanUpdate,
onPanEnd: _onPanEnd,
child: new Container(
width: double.infinity,
height: double.infinity,
child: new CustomPaint(
painter: _clockHandPainter,
)),
);
}
_onPanUpdate(DragUpdateDetails details) {
print(details);
RenderBox renderBox = context.findRenderObject();
var position = renderBox.globalToLocal(details.globalPosition);
angle = -coordinatesToRadians(_clockHandPainter.center, position);
print(angle);
initialize();
setState(() {});
}
_onPanEnd(_) {}
_onPanDown(DragDownDetails details) {
print(details);
print(angle);
}
initialize() {
_clockHandPainter =
new ClockHandPainter(widget.title, time, widget.color, angle);
}
double coordinatesToRadians(Offset center, Offset coords) {
var a = coords.dx - center.dx;
var b = center.dy - coords.dy;
return atan2(b, a);
}
}
用于绘制钟面
class ClockFaceComponent extends StatefulWidget {
@override
ClockFaceComponentState createState() {
return new ClockFaceComponentState();
}
}
class ClockFaceComponentState extends State<ClockFaceComponent> {
@override
Widget build(BuildContext context) {
return new Padding(
padding: const EdgeInsets.all(10.0),
child: new AspectRatio(
aspectRatio: 1.0,
child: new Container(
width: double.infinity,
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: ColorResource.clockBackgroundColor,
),
child: new Stack(
fit: StackFit.expand,
children: <Widget>[
//dial and numbers
new Container(
width: double.infinity,
height: double.infinity,
child: new CustomPaint(
painter: new ClockDialPainter(),
),
),
new Center(
child: new Container(
width: 40.0,
height: 40.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
)),
//centerpoint
new Center(
child: new Container(
width: 15.0,
height: 15.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: ColorResource.clockCenterColor,
),
),
),
getClockHands()
],
),
),
),
);
}
getClockHands() {
return new AspectRatio(
aspectRatio: 1.0,
child: new Stack(
fit: StackFit.expand,
children: getHands(),
));
}
getHands() {
List<Widget> widgets = new List();
List<Hands> hands = Hands.getHands();
for (Hands hand in hands) {
widgets.add(ClockHandComponent(
title: hand.title,
time: hand.time,
color: hand.color,
));
}
return widgets;
}
}