Flutter中如何为子组件出现时的重定位添加平滑动画?
实现布局重定位的平滑动画效果
要解决显示容器时Center组件重定位的突兀问题,我们可以通过Flutter的动画组件让尺寸变化和布局调整过程平滑过渡,以下是两种实用方案:
方案一:使用AnimatedSize自动处理尺寸过渡
AnimatedSize会监听子组件的尺寸变化,并自动生成平滑的过渡动画,刚好适配你的场景——当额外容器显示时,ListView的高度变化会被AnimatedSize捕捉,进而带动Center的重定位动画。
修改后的代码如下:
class MyWidget extends Stateful Widget { @override State<MyWidget> createState() => _MyWidgetState(); } class _MyWidgetState extends State<MyWidget> { bool _showContainer = false; @override Widget build(BuildContext context) { return Center( child: AnimatedSize( // 设置动画时长,可根据需求调整 duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, child: ListView( shrinkWrap: true, children: [ Text( 'Hello, World!', style: Theme.of(context).textTheme.headlineMedium, ), if (_showContainer) Container( color: Colors.pink, width: 100, height: 300, child: const Text("How to make the apparition smooth and animated"), ), ElevatedButton( onPressed: () => setState(() => _showContainer = true), child: const Text("SHOW CONTAINER"), ), ], ), ), ); } }
方案二:用SizeTransition单独控制容器的显示动画
如果只想针对弹出的容器做尺寸动画,同时让整体布局自然跟随调整,可以用SizeTransition包裹要显示的容器,它会沿着指定轴执行尺寸渐变动画。
修改后的代码示例:
class MyWidget extends Stateful Widget { @override State<MyWidget> createState() => _MyWidgetState(); } class _MyWidgetState extends State<MyWidget> with SingleTickerProviderStateMixin { bool _showContainer = false; late AnimationController _controller; late Animation<double> _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 300), vsync: this, ); _animation = CurvedAnimation(parent: _controller, curve: Curves.easeInOut); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Center( child: ListView( shrinkWrap: true, children: [ Text( 'Hello, World!', style: Theme.of(context).textTheme.headlineMedium, ), if (_showContainer) SizeTransition( sizeFactor: _animation, axis: Axis.vertical, child: Container( color: Colors.pink, width: 100, height: 300, child: const Text("How to make the apparition smooth and animated"), ), ), ElevatedButton( onPressed: () { setState(() => _showContainer = true); _controller.forward(); }, child: const Text("SHOW CONTAINER"), ), ], ), ); } }
说明
- 两种方案都可以实现平滑的布局重定位效果,你可以根据需求选择:
- 方案一更简洁,适合需要整体尺寸过渡的场景;
- 方案二更灵活,能单独控制容器的动画曲线和时长,还可以扩展其他动画效果。
- 动画时长和曲线可以根据产品需求调整,比如把
duration改成200ms让动画更快,或者换用Curves.easeOut让收尾更自然。
内容的提问来源于stack exchange,提问作者Stéphane de Luca
相关产品推荐
相关产品推荐

