颤动 - 在CustomPainters上获取触摸输入

时间:2018-05-24 21:24:58

标签: dart flutter

我有一个简单的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);
  }
}

2 个答案:

答案 0 :(得分:1)

我开发了一个名为 touchable

只需用CanvasTouchDetector包装您的CustomPaint小部件。它使用一个构建器函数作为参数,期望您的CustomPaint小部件如下所示。

CanvasTouchDetector(
    builder: (context) => 
        CustomPaint(
            painter: MyPainter(context)
        )
)

在CustomPainter类的paint方法中,创建并使用TouchyCanvas对象(使用从CanvasTouchDetector和canvas获得的上下文)来绘制具有不同手势回调的任何形状。

var myCanvas = TouchyCanvas(context,canvas);
myCanvas.drawRect( rect , Paint() , onTapDown: (tapDetail){
    //Do stuff here. Probably change your state and animate
});

答案 1 :(得分:1)

设置子项:CustomPaint小部件中的Container()!

InkWell(
      child: CustomPaint(painter: HexagonPainter(center, radius, color), child: Container(),),
      onTap: (){
        print('------yumcoder---');
      },

示例:

class HexagonPaint extends StatelessWidget {
  final Offset center;
  final double radius;
  final Color color;

  HexagonPaint(this.center, this.radius, this.color);

  @override
  Widget build(BuildContext context) {
    return InkWell(
      child: CustomPaint(painter: HexagonPainter(center, radius, color), child: Container(),),
      onTap: (){
        print('------yumcoder---');
      },
    );
  }
}

class HexagonPainter extends CustomPainter {
  static const int SIDES_OF_HEXAGON = 6;
  final double radius;
  final Offset center;
  final Color color;

  HexagonPainter(this.center, this.radius, this.color);

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()..color = this.color;
    Path path = createHexagonPath();
    canvas.drawPath(path, paint);
  }

  Path createHexagonPath() {
    final path = Path();
    var angle = (math.pi * 2) / SIDES_OF_HEXAGON;
    Offset firstPoint = Offset(radius * math.cos(0.0), radius * math.sin(0.0));
    path.moveTo(firstPoint.dx + center.dx, firstPoint.dy + center.dy);
    for (int i = 1; i <= SIDES_OF_HEXAGON; i++) {
      double x = radius * math.cos(angle * i) + center.dx;
      double y = radius * math.sin(angle * i) + center.dy;
      path.lineTo(x, y);
    }
    path.close();
    return path;
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}