You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中AnimatedBuilder结合CustomPainter动画视图停止更新问题求助

解决Flutter AnimatedBuilder + CustomPainter动画停更的问题

我之前也踩过这个一模一样的坑!这种现象本质上是CustomPainter的重绘逻辑没有正确触发导致的,跟AnimatedBuilder本身无关。

问题原因分析

当你在AnimatedBuilder的builder里只返回CustomPaint时,Flutter会检查BarPainter的shouldRepaint方法来决定是否需要重绘。如果你的BarPainter没有正确实现这个方法(比如默认返回false,或者没有对比percent的变化),那么即使_animationController.value在持续变化,Flutter也会认为不需要重绘CustomPainter,所以视图就停住了。

而当你加入Text组件后,Text的内容会随着动画值实时变化,它自身会触发重绘,这会带动AnimatedBuilder重新执行builder方法——每次都会创建一个新的BarPainter实例,相当于强制触发了CustomPainter的重绘,所以动画看起来就正常了,但这其实是个“治标不治本”的临时方案。

正确的解决方案

修改你的BarPainter,正确实现shouldRepaint方法,对比新旧委托的percent(以及其他可能变化的属性,比如color),当值发生变化时返回true:

class BarPainter extends CustomPainter {
  final Color color;
  final double percent;

  BarPainter({required this.color, required this.percent});

  @override
  void paint(Canvas canvas, Size size) {
    // 你的进度条绘制逻辑示例
    final paint = Paint()..color = color;
    final barWidth = size.width * percent;
    canvas.drawRect(Rect.fromLTWH(0, 0, barWidth, size.height), paint);
  }

  @override
  bool shouldRepaint(covariant BarPainter oldDelegate) {
    // 只要percent或color变化,就触发重绘
    return oldDelegate.percent != percent || oldDelegate.color != color;
  }
}

这样修改后,即使AnimatedBuilder的builder里只返回CustomPaint,Flutter也会在_animationController.value变化时,通过shouldRepaint的判断触发CustomPainter的重绘,动画就能正常运行了。

更高效的进阶写法

另外,也可以让BarPainter直接监听动画对象,这样能避免AnimatedBuilder反复创建Painter实例,性能更优:

class BarPainter extends CustomPainter {
  final Color color;
  final Animation<double> animation;

  // 通过super传入repaint参数,让Painter直接监听动画变化
  BarPainter({required this.color, required this.animation}) : super(repaint: animation);

  @override
  void paint(Canvas canvas, Size size) {
    final percent = animation.value;
    // 绘制逻辑...
  }

  @override
  bool shouldRepaint(covariant BarPainter oldDelegate) {
    // 只在color变化时才重绘,动画值变化由repaint参数处理
    return oldDelegate.color != color;
  }
}

使用时直接把动画对象传给Painter即可:

AnimatedBuilder(
  animation: _animationController,
  builder: (context, child) {
    return CustomPaint(
      painter: BarPainter(
        color: widget.color,
        animation: _animationController,
      ),
    );
  },
);

内容的提问来源于stack exchange,提问作者Anthony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 22:47:43