Flutter如何实现Dismissible弹窗拖拽时背景模糊度平滑调整
问题根因
- 你当前仅监听了用户触摸事件更新模糊度,
Dismissible松手后会执行内部自带的退场动画,这期间没有事件触发模糊度参数更新,导致模糊值停在松手时的数值,直到弹窗完全关闭才消失,过渡效果就会突兀。
最优解决方案(修改量最小)
不需要重构现有逻辑,只需要补充松手后的模糊度过渡动画即可,动画时长和 Dismissible 默认退场时长对齐即可:
- 首先给State类混入动画支持,并新增动画相关变量
class _YourDialogState extends State<YourDialog> with SingleTickerProviderStateMixin { // 原有变量 double _percentageHeight = 1; double? _initialPosY; // 新增动画变量 late AnimationController _blurController; late Animation<double> _blurAnimation; @override void initState() { super.initState(); // 时长和Dismissible默认退场时长保持一致 _blurController = AnimationController(vsync: this, duration: const Duration(milliseconds: 200)); _blurAnimation = Tween<double>(begin: 1, end: 0).animate(CurvedAnimation( parent: _blurController, curve: Curves.easeOut, ))..addListener(() { setState(() { _percentageHeight = _blurAnimation.value; }); }); } @override void dispose() { _blurController.dispose(); super.dispose(); } // 其余原有逻辑不变 }
- 给
Listener新增松手触发动画的回调,同时兼容用户拖拽一半取消的场景
Listener( // 新增松手回调 onPointerUp: (_) { if (_percentageHeight < 1) { _blurController.forward(from: _percentageHeight); } }, onPointerMove: (PointerMoveEvent event) { double percentage = 1 - (_initialPosY! - event.position.dy).abs() / _keyMyDialog.currentContext!.size!.height; // 拖拽回到原位时重置动画 if (percentage >= 1) { percentage = 1; _blurController.reset(); } setState(() => _percentageHeight = percentage); }, // 原有onPointerDown、onPointerSignal逻辑不变 child: Dismissible( // 原有Dismissible逻辑不变 ), )
高可控性替代方案
如果后续需要扩展更多弹窗交互,建议直接弃用Dismissible,自行通过GestureDetector+AnimationController实现拖拽和退场逻辑,全程可以实时获取弹窗偏移量,直接同步计算模糊度即可,不需要额外适配内部动画。
内容的提问来源于stack exchange,提问作者user12051965
相关产品推荐
相关产品推荐

