Flutter中Slide Animation未正常工作:容器滑动动画需求求助
问题分析与解决方案
你的代码问题在于布局约束和动画偏移逻辑不匹配:
Positioned同时设置left:0和right:10,导致外层Row的宽度被固定为屏幕宽度减10,容器的滑动范围被限制在这个窄区域内,无法实现从右下角到屏幕底部居中的效果SlideTransition的Offset参数是基于容器自身尺寸的比例偏移,原代码的Offset(1,1)仅能让容器向右偏移自身宽度,和你想要的全局位置滑动逻辑不符
下面提供两种简洁的解决方法:
方案一:使用AnimatedPositioned(推荐,逻辑直观)
直接通过动画控制容器的left/right属性,实现从右下角到底部居中的滑动:
import 'package:flutter/material.dart'; class ToastPage extends StatefulWidget { const ToastPage({super.key}); @override State<ToastPage> createState() => _ToastPageState(); } class _ToastPageState extends State<ToastPage> { bool _isCentered = false; @override void initState() { super.initState(); // 页面加载后自动启动动画 WidgetsBinding.instance.addPostFrameCallback((_) { setState(() => _isCentered = true); }); } @override Widget build(BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; const containerWidth = 200.0; const rightMargin = 10.0; final centerMargin = (screenWidth - containerWidth) / 2; return Scaffold( body: SizedBox.expand( child: Stack( children: [ MaterialButton( onPressed: () { // 先重置到右下角,再触发居中动画 setState(() => _isCentered = false); Future.delayed(const Duration(milliseconds: 100), () { setState(() => _isCentered = true); }); }, child: const Text("Animate"), ), AnimatedPositioned( duration: const Duration(seconds: 1), curve: Curves.easeInOut, bottom: 80, right: _isCentered ? centerMargin : rightMargin, left: _isCentered ? centerMargin : null, child: Container( height: 70, width: containerWidth, color: Colors.green, ), ), ], ), ), ); } }
方案二:修正SlideTransition的布局与偏移计算
如果坚持使用SlideTransition,需要调整布局约束并计算正确的偏移比例:
import 'package:flutter/material.dart'; class ToastPage extends StatefulWidget { const ToastPage({super.key}); @override State<ToastPage> createState() => _ToastPageState(); } class _ToastPageState extends State<ToastPage> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<Offset> _animation; @override void initState() { _controller = AnimationController(vsync: this, duration: const Duration(seconds: 1)); super.initState(); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; const containerWidth = 200.0; const rightMargin = 10.0; // 计算需要向左滑动的距离:从右下角到居中的水平偏移量 final moveDistance = (screenWidth - containerWidth) / 2 - rightMargin; _animation = Tween<Offset>( begin: const Offset(0, 0), end: Offset(-moveDistance / containerWidth, 0), ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut)); return Scaffold( body: SizedBox.expand( child: Stack( children: [ MaterialButton( onPressed: () { _controller.reset(); _controller.forward(); }, child: const Text("Animate"), ), Positioned( bottom: 80, right: rightMargin, child: SlideTransition( position: _animation, child: Container( height: 70, width: containerWidth, color: Colors.green, ), ), ), ], ), ), ); } }
内容的提问来源于stack exchange,提问作者muhammed jasir
相关产品推荐
相关产品推荐

