【问题标题】:When is shouldRepaint method from custom painter class in flutter called?什么时候调用flutter中自定义画家类的shouldRepaint方法?
【发布时间】:2019-05-30 02:31:23
【问题描述】:

我试图了解 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;
  }
}

【问题讨论】:

    标签: flutter


    【解决方案1】:

    来自DocsshouldRepaint()

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

    还有,

    即使 shouldRepaint 返回 false,paint 方法也可能会被调用(例如,如果需要重新绘制祖先或后代)。也有可能调用paint方法而根本没有调用shouldRepaint(例如,如果盒子改变了大小)


    所以,一个好方法是使用

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

    【讨论】:

    • 谢谢,有道理。
    猜你喜欢
    • 2018-10-23
    • 2022-07-12
    • 1970-01-01
    • 2010-11-04
    • 2011-07-21
    • 1970-01-01
    • 2015-07-13
    • 2012-11-30
    相关资源
    最近更新 更多