何时应从flutter中的自定义绘画程序类调用Repaint方法?

时间:2019-05-30 02:31:24

标签: flutter

我试图了解shouldRepaint的工作原理。我找到了一个教程,该教程在圆圈按钮周围绘制了一个表盘,以显示其值。该示例让shouldRepaint始终返回true。基本上,它只是在按钮周围绘制了一个局部圆圈以显示%值。如果值为50,则圆会绕过一半。

我将shouldRepaint设置为始终返回false,以查看会发生什么。仍然可以正确地绘制按钮圆圈。

我的理论是,当重绘有状态的小部件时,它将始终绘制。因此,当按钮值从40%变为50%时,无论如何,小部件都会重新绘制并完成绘制。

因此,如果状态改变时我的窗口小部件仍然被绘制,我什么时候应该使用shouldRepaint?

以下是该教程中的相关代码:

class HomeContent extends StatefulWidget {
  @override
  _HomeContentState createState() => _HomeContentState();
}

class _HomeContentState extends State<HomeContent> {
  int percentage;

  @override
  void initState() {
    super.initState();
    setState(() {
      percentage = 0;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Center(
      child: new Container(
        height: 200.0,
        width: 200.0,
        child: new CustomPaint(
          foregroundPainter: new MyPainter(
              lineColor: Colors.amber,
          completeColor: Colors.blueAccent,
          completePercent: percentage,
          width: 8.0),
          child: new Padding(
          padding: const EdgeInsets.all(8.0),
        child: new RaisedButton(
            color: Colors.purple,
            splashColor: Colors.blueAccent,
            shape: new CircleBorder(),
            child: new Text("$percentage%"),
            onPressed: () {
              setState(() {
                percentage += 10;
                if (percentage > 100) {
                  percentage = 0;
                }
              });
            }),
          ),
        ),
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  Color lineColor;
  Color completeColor;
  int completePercent;
  double width;

  MyPainter(
  {this.lineColor, this.completeColor, this.completePercent, this.width});

  @override
  void paint(Canvas canvas, Size size) {
    Paint line = new Paint()
      ..color = lineColor
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke
      ..strokeWidth = width;
    Paint complete = new Paint()
      ..color = completeColor
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke
      ..strokeWidth = width;
    Offset center = new Offset(size.width / 2, size.height / 2);
    double radius = min(size.width / 2, size.height / 2);
    canvas.drawCircle(center, radius, line);
    double arcAngle = 2 * pi * (completePercent / 100.0);
    if (arcAngle >= 2 * pi) arcAngle = 2 * pi - 0.001;  // cannot draw a complete circle arc
    canvas.drawArc(new Rect.fromCircle(center: center, radius: radius), -pi / 2,
    arcAngle, false, complete);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

2 个答案:

答案 0 :(得分:1)

来自DocsshouldRepaint()

  

如果新实例表示的信息与旧实例不同,则该方法应返回true,否则应返回false

也是

  

即使shouldRepaint返回false,也有可能调用paint方法(例如,如果需要重绘祖先或后代)。也有可能在完全不应该调用shouldRepaint的情况下调用paint方法(例如,如果框更改了大小)


所以,一个好方法就是使用

@override
bool shouldRepaint(MyPainter oldDelegate) => 
    oldDelegate.completePercent != completePercent;

答案 1 :(得分:0)

仅当CustomPainter已更改时才应重新绘制。这是我通常要做的

return this!=oldDelegate;