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

Dart Flutter:如何从ScopedModel触发其子Widget的动画?

实现Flutter方块的渐隐消失效果

嘿,我懂你遇到的困扰了——直接让方块瞬间消失太生硬,想做渐隐但AnimationController的vsync参数总是报错对吧?别慌,我给你一套完整的解决方案,一步步来搞定:

核心问题解析

AnimationController 需要一个 TickerProvider 来同步动画与屏幕刷新节奏,通常我们会让页面的State类混入 SingleTickerProviderStateMixin(单动画场景下用这个足够),这样this就能作为合法的vsync参数。之前报错大概率是因为你没正确混入这个Mixin,或是在生命周期外初始化了控制器。

完整代码实现

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('渐隐方块示例')),
        body: const FadingBoxDemo(),
      ),
    );
  }
}

class FadingBoxDemo extends StatefulWidget {
  const FadingBoxDemo({super.key});

  @override
  State<FadingBoxDemo> createState() => _FadingBoxDemoState();
}

// 关键:混入SingleTickerProviderStateMixin提供vsync能力
class _FadingBoxDemoState extends State<FadingBoxDemo> with SingleTickerProviderStateMixin {
  late AnimationController _fadeController;
  late Animation<double> _fadeAnimation;
  bool _isBoxVisible = false;

  @override
  void initState() {
    super.initState();
    // 初始化动画控制器,时长设为3秒(可按需调整)
    _fadeController = AnimationController(
      duration: const Duration(seconds: 3),
      vsync: this, // 混入Mixin后,this就是合法的TickerProvider
    );

    // 创建透明度动画:从完全可见(1.0)到完全透明(0.0)
    _fadeAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(_fadeController);

    // 监听动画状态,结束后隐藏方块并重置控制器
    _fadeController.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        setState(() {
          _isBoxVisible = false;
        });
        _fadeController.reset(); // 重置后可重复触发动画
      }
    });
  }

  @override
  void dispose() {
    // 页面销毁时释放控制器,避免内存泄漏
    _fadeController.dispose();
    super.dispose();
  }

  void _triggerFade() {
    setState(() {
      _isBoxVisible = true;
    });
    // 启动渐隐动画
    _fadeController.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // 红色触发按钮
          ElevatedButton(
            style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
            onPressed: _triggerFade,
            child: const Text('显示方块并渐隐'),
          ),
          const SizedBox(height: 20),
          // 带渐隐效果的方块
          if (_isBoxVisible)
            AnimatedOpacity(
              opacity: _fadeAnimation.value,
              duration: _fadeController.duration!,
              child: Container(
                width: 150,
                height: 150,
                color: Colors.blue,
              ),
            ),
        ],
      ),
    );
  }
}

关键细节说明

  • SingleTickerProviderStateMixin:这个Mixin给State类赋予了Ticker能力,确保动画和屏幕帧率完美同步,直接解决vsync参数的报错问题。
  • 动画状态监听:通过addStatusListener捕获动画完成状态,结束后自动隐藏方块并重置控制器,保证下次点击按钮能正常触发新的动画。
  • AnimatedOpacity:Flutter封装好的透明度动画组件,直接绑定动画值就能实现平滑过渡,比手动用Opacity组件更省心。

如果不想用AnimatedOpacity,也可以直接用基础的Opacity组件:

Opacity(
  opacity: _fadeAnimation.value,
  child: Container(
    width: 150,
    height: 150,
    color: Colors.blue,
  ),
)

这样就能实现方块在3秒内平滑渐隐消失的效果啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:01:25