Flutter问题:实现按钮后方滑入的Bottom Sheet动画
修复Bottom Sheet从屏幕底部滑入的动画问题
你的问题核心在于两点:一是用AnimatedSize仅改变容器高度,导致视图向上扩展而非从底部滑入;二是将触发按钮嵌套在Bottom Sheet内部,按钮位置会随Bottom Sheet尺寸变化而移动。以下是具体修复方案:
核心改动思路
- 放弃
Scaffold的bottomSheet属性,改用手动布局控制Bottom Sheet初始位置,确保其完全隐藏在屏幕下方 - 使用平移动画替代尺寸变化动画,实现从屏幕底部滑入的效果
- 将触发按钮固定在屏幕底部最上层,与Bottom Sheet的动画状态解耦
修复后的完整代码
import 'package:flutter/material.dart'; class BottomSheetExample extends StatefulWidget { const BottomSheetExample({super.key}); @override State<BottomSheetExample> createState() => _BottomSheetExampleState(); } class _BottomSheetExampleState extends State<BottomSheetExample> { bool _isSheetExpanded = false; final double _sheetHeight = 200; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.green, body: const Center(child: Text('Body')), // 固定触发按钮在屏幕底部最上层 floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, floatingActionButton: ElevatedButton( onPressed: () => setState(() => _isSheetExpanded = !_isSheetExpanded), child: const Text("Toggle"), ), // 用AnimatedContainer实现滑入动画 bottomNavigationBar: AnimatedContainer( duration: const Duration(milliseconds: 500), curve: Curves.easeInOut, // 初始时将Bottom Sheet移出屏幕,展开时复位 transform: Matrix4.translationValues(0, _isSheetExpanded ? 0 : _sheetHeight, 0), height: _sheetHeight, child: Container( color: Colors.amber, padding: const EdgeInsets.all(20), child: const Center(child: Text('Bottom Sheet')), ), ), ); } }
代码说明
- 动画逻辑:通过
AnimatedContainer的transform属性控制Y轴位移,初始状态下Bottom Sheet完全位于屏幕下方,展开时位移归零,实现从底部滑入的自然动画 - 按钮独立:将按钮放在
floatingActionButton并设置centerFloat位置,始终固定在屏幕底部最上层,不会随Bottom Sheet移动 - 状态控制:用
_isSheetExpanded布尔值切换展开/收起状态,动画时长和曲线可根据需求调整
如果偏好使用SlideTransition实现动画,可替换bottomNavigationBar部分为以下代码(需混入SingleTickerProviderStateMixin):
bottomNavigationBar: SlideTransition( position: Tween<Offset>( begin: const Offset(0, 1), // 初始在屏幕外(下方) end: const Offset(0, 0), // 展开时回到屏幕底部 ).animate(CurvedAnimation( parent: AnimationController( vsync: this, duration: const Duration(milliseconds: 500), )..forward(from: _isSheetExpanded ? 1 : 0), curve: Curves.easeInOut, )), child: Container( height: _sheetHeight, color: Colors.amber, padding: const EdgeInsets.all(20), child: const Center(child: Text('Bottom Sheet')), ), )
内容的提问来源于stack exchange,提问作者Denis
相关产品推荐
相关产品推荐

