我有一个简单的CustomPaint / CustomPainter,它绘制了一个圆的段(下面的代码)。我已经读到我不能使用GestureDetector,因为它不是正确的小部件,那么获取输入的最佳方法是什么?
我将有很多段,所以我需要像素精确的触摸位置。
我想到了两种可能性:
我的CustomPainter:
class _SegmentPainter extends CustomPainter { static const offset = -pi/2; double start; double end; double innerRadius; double outerRadius; Color color; _SegmentPainter(this.start, this.end, {this.innerRadius = 0.0, this.outerRadius, this.color}); @override bool shouldRepaint(CustomPainter oldDelegate) => this == oldDelegate; @override bool shouldRebuildSemantics(CustomPainter oldDelegate) => this == oldDelegate; @override void paint(Canvas canvas, Size size) { Path path = new Path(); path.arcTo(Rect.fromCircle(center: new Offset(0.0, 0.0), radius: outerRadius), offset + start, end-start, true); path.relativeLineTo(-cos(offset + end)*(outerRadius-innerRadius), -sin(offset + end)*(outerRadius-innerRadius)); path.arcTo(Rect.fromCircle(center: new Offset(0.0, 0.0), radius: innerRadius), offset + end, start-end, false); path.close(); canvas.drawPath(path, new Paint()..color = color..style = PaintingStyle.fill); } }
我同意您必须将CustomPainter放入具有大小的窗口小部件中。它可能是一个SizedBox,所以我在这里使用了它。幸运的是,您不需要进行手动命中测试,因为CustomPainter可以通过一些重构即可为您处理。首先要注意的是,不需要在每个paint()上重建路径- 可以在构造函数中构建路径。这使CustomPainter的hitTest可以简单地询问水龙头在路径内还是路径外。
class _SegmentPainter extends CustomPainter { static const offset = -pi / 2; double start; double end; double innerRadius; double outerRadius; Color color; Path path; _SegmentPainter( this.start, this.end, this.innerRadius, this.outerRadius, this.color) { path = new Path() ..arcTo( Rect.fromCircle(center: new Offset(0.0, 0.0), radius: outerRadius), offset + start, end - start, true) ..relativeLineTo(-cos(offset + end) * (outerRadius - innerRadius), -sin(offset + end) * (outerRadius - innerRadius)) ..arcTo( Rect.fromCircle(center: new Offset(0.0, 0.0), radius: innerRadius), offset + end, start - end, false) ..close(); } @override bool shouldRepaint(_SegmentPainter oldDelegate) { return oldDelegate.start != start || oldDelegate.end != end || oldDelegate.innerRadius != innerRadius || oldDelegate.outerRadius != outerRadius || oldDelegate.color != color; } @override bool shouldRebuildSemantics(_SegmentPainter oldDelegate) => true; @override void paint(Canvas canvas, Size size) { canvas.drawPath( path, new Paint() ..color = color ..style = PaintingStyle.fill); } @override bool hitTest(Offset position) { return path.contains(position); } } class SegmentWidget extends StatelessWidget { @override Widget build(BuildContext context) { return new GestureDetector( onTap: () => print('tap'), child: new SizedBox( width: 250.0, height: 250.0, child: new CustomPaint( painter: new _SegmentPainter(0.0, 2.8, 150.0, 200.0, Colors.orange), ), ), ); } }
我使用了Dart ..(级联)语法来清理路径。(我认为您的should...测试被否定了。)我添加了一个StatelessWidget,作为SizedBoxand 的主页GestureDetector。
..
should...
SizedBox
GestureDetector