Flutter Dismissible滑动黑屏问题:如何显示上一页或替代方案
解决Dismissible滑动时黑屏并显示上一页的问题
问题原因
默认MaterialPageRoute是不透明的,会完全覆盖上一页;同时Dismissible未设置background属性时,默认显示黑色背景,导致滑动时出现黑屏。
解决方案一:透明路由 + 自定义Dismissible背景
通过修改路由为透明模式,并配置Dismissible的背景为透明,实现滑动时显示上一页的效果:
- 修改跳转路由为透明路由
将MaterialPageRoute替换为PageRouteBuilder,设置opaque: false:
// 在myFirstPag的onTap中修改 Navigator.of(context).push( PageRouteBuilder( opaque: false, // 设为透明 pageBuilder: (context, animation, secondaryAnimation) => const mySecPag(), ), );
- 调整第二页的Dismissible配置
给Dismissible添加透明的background,并保持Scaffold原有背景色:
class mySecPagState extends State<mySecPag> { @override Widget build(BuildContext context) { return Dismissible( key: const Key('some key here'), direction: DismissDirection.down, onDismissed: (l) { Navigator.pop(context); }, // 设置透明背景,滑动时露出上一页 background: Container(color: Colors.transparent), child: const Scaffold( backgroundColor: Colors.yellowAccent, body: Center(child: Text('my sec page')), ), ); } }
解决方案二:自定义滑动返回手势(替代Dismissible)
如果Dismissible的效果不符合预期,可通过GestureDetector结合动画控制器实现更灵活的滑动返回:
class mySecPag extends StatefulWidget { const mySecPag({Key? key}) : super(key: key); @override mySecPagState createState() => mySecPagState(); } class mySecPagState extends State<mySecPag> with SingleTickerProviderStateMixin { late AnimationController _animationController; late Animation<Offset> _offsetAnimation; double _dragStartY = 0; @override void initState() { super.initState(); _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 300), ); _offsetAnimation = Tween<Offset>( begin: Offset.zero, end: const Offset(0, 1), // 向下滑出屏幕 ).animate(CurvedAnimation( parent: _animationController, curve: Curves.easeInOut, )); } @override void dispose() { _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return GestureDetector( onVerticalDragStart: (details) { _dragStartY = details.globalPosition.dy; }, onVerticalDragUpdate: (details) { double offset = details.globalPosition.dy - _dragStartY; // 仅处理向下拖拽的进度 if (offset > 0) { _animationController.value = offset / MediaQuery.of(context).size.height; } }, onVerticalDragEnd: (details) { // 拖拽距离超过屏幕1/3则退出页面,否则回弹 if (_animationController.value > 1/3) { _animationController.forward().then((_) { Navigator.pop(context); }); } else { _animationController.reverse(); } }, child: SlideTransition( position: _offsetAnimation, child: const Scaffold( backgroundColor: Colors.yellowAccent, body: Center(child: Text('my sec page')), ), ), ); } }
同时需保持跳转路由为透明模式(同方案一的路由设置),确保滑动过程中能实时看到上一页。
内容的提问来源于stack exchange,提问作者Mohammed Hamdan
相关产品推荐
相关产品推荐

