如何在Flutter中实现多组件带延迟的滑入滑出序列动画?
问题根因
你遇到的动画顺序颠倒问题,是flutter_sequence_animation包的默认值逻辑导致的:当某个动画tag的时间线存在空白段(即还未到该tag首个动画的起始时间时),包不会自动使用你定义的首个animatable的begin值,而是直接返回该tag最后一段动画的end值,这就导致最后定义的test元素在动画刚启动时就已经处于最终位置,看起来像是最先展示的。
解决方案
给每个动画tag都补一段从0到该tag首个动画起始时间的固定值补间,填补时间线的空白段,保证动画未启动时元素保持在初始的屏幕外位置。
修改后的完整代码如下:
import 'package:flutter/material.dart'; import 'package:flutter_sequence_animation/flutter_sequence_animation.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key? key}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin { late AnimationController controller; late SequenceAnimation sequenceAnimation; void initAnimation() { double screenSize = 500; // MediaQuery.of(context).size.width; controller = AnimationController( vsync: this, duration: Duration(milliseconds: 5500)); sequenceAnimation = SequenceAnimationBuilder() // 填补source标签的初始空白段,保持初始值-100 .addAnimatable( animatable: Tween<double>(begin: -100, end: -100), tag: 'source', curve: Curves.linear, from: Duration.zero, to: Duration.zero, ) .addAnimatable( animatable: Tween<double>(begin: -100, end: 200), tag: 'source', curve: Curves.easeInBack, from: Duration(milliseconds: 0), to: Duration(milliseconds: 1000), ) .addAnimatable( animatable: Tween<double>(begin: 200, end: screenSize), tag: 'source', curve: Curves.easeInBack, from: Duration(milliseconds: 1250), to: Duration(milliseconds: 2250), ) // 填补plane标签的初始空白段,保持初始值-100 .addAnimatable( animatable: Tween<double>(begin: -100, end: -100), tag: 'plane', curve: Curves.linear, from: Duration.zero, to: Duration(milliseconds: 2250), ) .addAnimatable( animatable: Tween<double>(begin: -100, end: screenSize), from: Duration(milliseconds: 2250), to: Duration(milliseconds: 2500), curve: Curves.easeInBack, tag: 'plane', ) // 填补test标签的初始空白段,保持初始值-200 .addAnimatable( animatable: Tween<double>(begin: -200, end: -200), tag: 'test', curve: Curves.linear, from: Duration.zero, to: Duration(milliseconds: 3500), ) .addAnimatable( animatable: Tween<double>(begin: -200, end: 200), tag: 'test', curve: Curves.easeInBack, from: Duration(milliseconds: 3500), to: Duration(milliseconds: 4500), ) .addAnimatableAfterLastOneWithTag( animatable: Tween<double>(begin: 200, end: screenSize), tag: 'test', curve: Curves.easeInBack, duration: Duration(milliseconds: 1000), lastTag: 'test', ) .animate(controller); controller.repeat(); } @override void initState() { super.initState(); initAnimation(); } @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ AnimatedBuilder( animation: controller, builder: (context, child) => Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Container( color: Colors.blue, height: 100, width: 100, transform: Matrix4.translationValues( sequenceAnimation["source"].value, 0.0, 0.0, ), ), ], ), ), AnimatedBuilder( animation: controller, builder: (context, child) => Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Container( color: Colors.red, height: 100, width: 100, transform: Matrix4.translationValues( sequenceAnimation["test"].value, 0.0, 0.0, ), child: Text('Test'), ), ], ), ), AnimatedBuilder( animation: controller, builder: (context, child) => Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Container( color: Colors.orange, height: 100, width: 100, transform: Matrix4.translationValues( sequenceAnimation["plane"].value, 0.0, 0.0, ), ), ], ), ), ], ), ); } }
额外说明
如果需要调整元素的层级顺序,直接调换Stack中子组件的排列顺序即可,排在后面的子组件会显示在更上层。
内容的提问来源于stack exchange,提问作者Yasin ilhan
相关产品推荐
相关产品推荐

