Flutter实现渐显滑动动画:SKYGOAL文本动画求助
问题描述
我正在Flutter应用中实现启动页效果,但无法实现“SKYGOAL”文本的渐显+滑动动画。已经用AnimatedContainer或AnimatedOpacity完成了其他组件的动画,作为动画新手不知道该怎么处理这个需求,求帮助!
当前相关代码片段:
class SplashScreen1 extends StatefulWidget { const SplashScreen1({Key? key}) : super(key: key); @override State<SplashScreen1> createState() => _SplashScreen1State(); } class _SplashScreen1State extends State<SplashScreen1> with SingleTickerProviderStateMixin { double _skygoalLogoOpacity = 0; double _syjOpacity = 0; double _skygoalTextWidth = 0; @override void initState() { super.initState(); Future.delayed(const Duration(seconds: 0)).then((value) => setState(() { _skygoalLogoOpacity = 1; _syjOpacity = 1; _skygoalTextWidth = 2000; })); Future.delayed(const Duration(milliseconds: 4800)).then((value) => Navigator.pushReplacement(context, AnimatedPageRoute(SplashScreen2()))); } @override Widget build(BuildContext context) { return Scaffold( body: Container( color: Color(0xFF0E3C6E), width: MediaQuery.of(context).size.width, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: [ SizedBox(height: 250,), Stack( children: [ Container( decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white ), height: 185, width: 185, ), AnimatedOpacity( duration: const Duration(milliseconds: 1000), opacity: _skygoalLogoOpacity, child: Container( padding: EdgeInsets.only(top: 20), child: Image.asset("assets/images/skygoal-logo.png"), width: 164, ), ), ], ), Stack( children: [ AnimatedOpacity( duration: const Duration(milliseconds: 2000), opacity: _syjOpacity, child: Container( margin: EdgeInsets.only(left: 40, top: 37), height: 29, width: 153, child: Image.asset("assets/images/start-your-journey.png"), ), ), Container( margin: EdgeInsets.only(top: 5,left: 20), child: Text( "SKYGOAL", style: GoogleFonts.poppins( fontSize: 30, fontWeight: FontWeight.w800, color: Colors.white ), textAlign: TextAlign.center, ), ), ], ), Spacer(), Text( "By Skygoal", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 13 ), ), Container( margin: EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10) ), height: 5, width: 134, ) ], ), ), ); } }
解决方案
要实现文本的渐显+滑动组合动画,可以用AnimationController配合SlideTransition和FadeTransition的组合,以下是修改后的完整代码:
class SplashScreen1 extends StatefulWidget { const SplashScreen1({Key? key}) : super(key: key); @override State<SplashScreen1> createState() => _SplashScreen1State(); } class _SplashScreen1State extends State<SplashScreen1> with SingleTickerProviderStateMixin { double _skygoalLogoOpacity = 0; double _syjOpacity = 0; // 新增动画控制器与动画对象 late AnimationController _textAnimationController; late Animation<double> _textOpacityAnimation; late Animation<Offset> _textSlideAnimation; @override void initState() { super.initState(); // 初始化动画控制器,时长可按需调整 _textAnimationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 1500), ); // 渐显动画:从完全透明到完全显示 _textOpacityAnimation = Tween<double>(begin: 0, end: 1).animate( CurvedAnimation(parent: _textAnimationController, curve: Curves.easeInOut), ); // 滑动动画:从左侧偏移位置滑到目标位置(可修改偏移量调整滑动方向) _textSlideAnimation = Tween<Offset>(begin: const Offset(-0.5, 0), end: Offset.zero).animate( CurvedAnimation(parent: _textAnimationController, curve: Curves.easeOut), ); // 控制动画启动时机,配合其他组件动画节奏调整延迟 Future.delayed(const Duration(milliseconds: 500), () { _textAnimationController.forward(); }); // 原有其他组件动画逻辑 Future.delayed(const Duration(seconds: 0)).then((value) => setState(() { _skygoalLogoOpacity = 1; _syjOpacity = 1; })); Future.delayed(const Duration(milliseconds: 4800)).then((value) => Navigator.pushReplacement(context, AnimatedPageRoute(SplashScreen2()))); } @override void dispose() { // 销毁控制器,避免内存泄漏 _textAnimationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Container( color: const Color(0xFF0E3C6E), width: MediaQuery.of(context).size.width, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: [ const SizedBox(height: 250), Stack( children: [ Container( decoration: const BoxDecoration( shape: BoxShape.circle, color: Colors.white, ), height: 185, width: 185, ), AnimatedOpacity( duration: const Duration(milliseconds: 1000), opacity: _skygoalLogoOpacity, child: Container( padding: const EdgeInsets.only(top: 20), child: Image.asset("assets/images/skygoal-logo.png"), width: 164, ), ), ], ), Stack( children: [ AnimatedOpacity( duration: const Duration(milliseconds: 2000), opacity: _syjOpacity, child: Container( margin: const EdgeInsets.only(left: 40, top: 37), height: 29, width: 153, child: Image.asset("assets/images/start-your-journey.png"), ), ), // 用SlideTransition包裹FadeTransition,实现滑动+渐显的组合动画 Container( margin: const EdgeInsets.only(top: 5, left: 20), child: SlideTransition( position: _textSlideAnimation, child: FadeTransition( opacity: _textOpacityAnimation, child: Text( "SKYGOAL", style: GoogleFonts.poppins( fontSize: 30, fontWeight: FontWeight.w800, color: Colors.white, ), textAlign: TextAlign.center, ), ), ), ), ], ), const Spacer(), const Text( "By Skygoal", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 13, ), ), Container( margin: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), ), height: 5, width: 134, ) ], ), ), ); } }
关键修改说明:
- 新增
AnimationController统一管理动画的时长和运动曲线 - 分别创建渐显、滑动两个动画对象,可自定义初始/结束值调整动画效果
- 通过
SlideTransition与FadeTransition的嵌套,让两个动画同时生效 - 控制动画启动的延迟时间,保证与其他组件的动画节奏匹配
- 在组件销毁时释放动画控制器,避免内存泄漏
内容的提问来源于stack exchange,提问作者Necromancer
相关产品推荐
相关产品推荐

