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

如何监听AnimatedFoo组件动画完成?AnimatedSize使用疑问

如何监听AnimatedSize动画完成

AnimatedSize确实没提供直接的动画完成回调,也不支持传入自定义AnimatedController,给你两种可行的实现方式:

方法一:手动用AnimationController+AnimatedBuilder实现

自己创建控制器和尺寸动画,通过监听器捕获完成事件,灵活性更高:

late AnimationController _sizeController;
late Animation<double> _heightAnimation;

@override
void initState() {
  super.initState();
  _sizeController = AnimationController(
    duration: const Duration(milliseconds: 500),
    vsync: this,
  );
  // 定义尺寸从100到300的动画,曲线用你需要的bounceOut
  _heightAnimation = Tween<double>(begin: 100, end: 300).animate(
    CurvedAnimation(parent: _sizeController, curve: Curves.bounceOut),
  )..addStatusListener((status) {
      // 动画完成时触发回调
      if (status == AnimationStatus.completed) {
        _onAnimationFinish();
      }
    });
}

// 动画完成后执行的函数
void _onAnimationFinish() {
  print("动画结束了");
  // 这里写你的业务逻辑
}

// 调用这个方法触发动画,比如按钮点击事件里调用
void _startAnimation() {
  _sizeController.forward();
}

@override
void dispose() {
  _sizeController.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return AnimatedBuilder(
    animation: _heightAnimation,
    builder: (context, child) {
      return Container(
        height: _heightAnimation.value,
        width: double.infinity,
        color: Colors.blue,
        child: child,
      );
    },
    child: const Text("你的子组件内容"),
  );
}

方法二:通过监听尺寸变化判断完成

如果不想手动实现动画,可以通过addPostFrameCallback循环检查组件尺寸,达到目标尺寸时触发回调:

double _currentHeight = 100;
final double _targetHeight = 300;
bool _isAnimationDone = false;

// 触发动画的方法
void _triggerAnimation() {
  setState(() {
    _currentHeight = _targetHeight;
    _isAnimationDone = false;
  });
  WidgetsBinding.instance.addPostFrameCallback((_) {
    _checkIfAnimationDone();
  });
}

void _checkIfAnimationDone() {
  if (!_isAnimationDone) {
    final renderBox = context.findRenderObject() as RenderBox;
    if (renderBox.size.height == _targetHeight) {
      _isAnimationDone = true;
      _onAnimationFinish();
    } else {
      // 下一帧继续检查
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _checkIfAnimationDone();
      });
    }
  }
}

void _onAnimationFinish() {
  print("动画完成");
  // 业务逻辑写这
}

@override
Widget build(BuildContext context) {
  return AnimatedSize(
    duration: const Duration(milliseconds: 500),
    curve: Curves.bounceOut,
    child: Container(
      height: _currentHeight,
      width: double.infinity,
      color: Colors.blue,
      child: const Text("你的子组件"),
    ),
  );
}

方法二更适合简单场景,但要确保能正确获取组件的RenderBox,且目标尺寸是明确的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:45:43