Flutter实现文本从屏幕左侧飞入居中动画的方法
Flutter实现依次飞入的文本动画
你可以通过两种方式实现这个需求:原生Flutter动画API(无需第三方包)或者使用专门的动画编排包简化开发。
一、原生实现(推荐,轻量可控)
利用AnimationController、Tween和SlideTransition组合,配合Future.delayed控制动画启动间隔,就能实现文本依次从左侧飞入中心的效果。
完整代码示例
import 'package:flutter/material.dart'; class FlyInTextPage extends StatefulWidget { const FlyInTextPage({super.key}); @override State<FlyInTextPage> createState() => _FlyInTextPageState(); } class _FlyInTextPageState extends State<FlyInTextPage> with TickerProviderStateMixin { late final List<AnimationController> _controllers; late final List<Animation<Offset>> _animations; final List<String> _texts = ["第一段文本", "第二段文本", "第三段文本"]; @override void initState() { super.initState(); // 初始化3个动画控制器,每个控制一段文本的动画 _controllers = List.generate(3, (index) => AnimationController( duration: const Duration(milliseconds: 800), vsync: this, )); // 定义从左侧(-1,0)到中心(0,0)的位移动画 _animations = _controllers.map((controller) => Tween<Offset>( begin: const Offset(-1.0, 0.0), end: Offset.zero, ).animate(CurvedAnimation( parent: controller, curve: Curves.easeOut, ))).toList(); // 依次启动动画,间隔1秒 _startAnimations(); } void _startAnimations() async { await Future.delayed(Duration.zero); // 确保Widget已完成挂载 _controllers[0].forward(); await Future.delayed(const Duration(seconds: 1)); _controllers[1].forward(); await Future.delayed(const Duration(seconds: 1)); _controllers[2].forward(); } @override void dispose() { // 销毁控制器,避免内存泄漏 for (var controller in _controllers) controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(3, (index) { return SlideTransition( position: _animations[index], child: Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: Text(_texts[index], style: const TextStyle(fontSize: 24)), ), ); }), ), ), ); } }
关键说明
SlideTransition:负责将位移动画应用到文本组件,实现飞入效果AnimationController:控制动画的启动、停止及持续时长Future.delayed:精准控制每段文本动画的启动间隔
二、第三方包实现(复杂场景推荐)
如果需要编排更复杂的序列动画,可以使用flutter_sequence_animation包,它能更直观地定义多动画的时间线。
步骤1:添加依赖
在pubspec.yaml中加入:
dependencies: flutter_sequence_animation: ^2.0.0
步骤2:完整代码示例
import 'package:flutter/material.dart'; import 'package:flutter_sequence_animation/flutter_sequence_animation.dart'; class SequenceFlyInPage extends StatefulWidget { const SequenceFlyInPage({super.key}); @override State<SequenceFlyInPage> createState() => _SequenceFlyInPageState(); } class _SequenceFlyInPageState extends State<SequenceFlyInPage> with TickerProviderStateMixin { late final AnimationController _controller; late final SequenceAnimation _sequenceAnimation; final List<String> _texts = ["第一段文本", "第二段文本", "第三段文本"]; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(seconds: 4), // 总时长覆盖所有动画周期 vsync: this, ); // 编排序列动画:依次定义每段文本的动画时间区间 _sequenceAnimation = SequenceAnimationBuilder() .addAnimatable( animatable: Tween<Offset>(begin: const Offset(-1,0), end: Offset.zero), from: const Duration(seconds: 0), to: const Duration(milliseconds: 800), tag: "text0", curve: Curves.easeOut, ) .addAnimatable( animatable: Tween<Offset>(begin: const Offset(-1,0), end: Offset.zero), from: const Duration(seconds: 1), to: const Duration(milliseconds: 1800), tag: "text1", curve: Curves.easeOut, ) .addAnimatable( animatable: Tween<Offset>(begin: const Offset(-1,0), end: Offset.zero), from: const Duration(seconds: 2), to: const Duration(milliseconds: 2800), tag: "text2", curve: Curves.easeOut, ) .animate(_controller); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SlideTransition( position: _sequenceAnimation["text0"]!.value, child: Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: Text(_texts[0], style: const TextStyle(fontSize:24)), ), ), SlideTransition( position: _sequenceAnimation["text1"]!.value, child: Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: Text(_texts[1], style: const TextStyle(fontSize:24)), ), ), SlideTransition( position: _sequenceAnimation["text2"]!.value, child: Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: Text(_texts[2], style: const TextStyle(fontSize:24)), ), ), ], ), ), ); } }
总结
- 简单场景:优先用原生API,无需额外依赖,性能更优
- 复杂序列动画:使用
flutter_sequence_animation简化时间线编排
内容的提问来源于stack exchange,提问作者Arjun Malhotra
相关产品推荐
相关产品推荐

