Flutter-在CustomPainters上获得触摸输入
我有一个简单的CustomPaint /
CustomPainter,它绘制了一个圆的段(下面的代码)。我已经读到我不能使用GestureDetector,因为它不是正确的小部件,那么获取输入的最佳方法是什么?
我将有很多段,所以我需要像素精确的触摸位置。
我想到了两种可能性:
- 将画家放在SizedBox中并获取触摸坐标,然后手动计算它是否在路径内。但这将使很多代码加倍。
- 使用Material类和自定义BorderShape。这将很方便,但对我来说似乎很客气。
我的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,作为SizedBox
and
的主页GestureDetector
。
以上是 Flutter-在CustomPainters上获得触摸输入 的全部内容, 来源链接: utcz.com/qa/415915.html