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,作为SizedBoxand

的主页GestureDetector

以上是 Flutter-在CustomPainters上获得触摸输入 的全部内容, 来源链接: utcz.com/qa/415915.html

回到顶部