使用WillPopScope即可,重点onWillPop方法:
Future<bool> _onWillPop()=>new Future.value(false);
由于要弹出dialog,我这里是禁掉返回按钮,当然也可以在这里做一下其他操作,比如连续点击两次返回,又或者连续pop两次把dialog和页面一起返回掉。
import 'package:flutter/material.dart'; class RewriteShowDialog { RewriteShowDialog({ @required this.context, this.child, this.barrierColor = Colors.black54, this.barrierDismissible = false, this.elevation = 0, this.padding }){ _showGeneralDialog( barrierDismissible: barrierDismissible, barrierColor: barrierColor, builder: (BuildContext context) { /// AnimatedPadding代替dialog /// dialog没有提供修改padding的属性,本身也是调用的AnimatedPadding Future<bool> _onWillPop()=>new Future.value(false); return WillPopScope( onWillPop:_onWillPop, child: AnimatedPadding( padding: padding == null ? EdgeInsets.symmetric(horizontal: 32, vertical: 24) : padding, duration: Duration(milliseconds: 100), curve: Curves.decelerate, child: MediaQuery.removeViewInsets( removeLeft: true, removeTop: true, removeRight: true, removeBottom: true, context: context, child: Center( child: Material( elevation: elevation, borderRadius: BorderRadius.circular(12), child: child ), ), ), ), ); } ); } final BuildContext context; /// 内容 final Widget child; /// 点击背景是否可以关闭弹窗 final bool barrierDismissible; /// 背景颜色 final Color barrierColor; /// 阴影 final double elevation; /// 内边距 final EdgeInsets padding; /// 重写showGeneralDialog /// 系统自带的背景背景透明不能修改 void _showGeneralDialog({ Widget Function(BuildContext) builder, Widget child, bool barrierDismissible, Color barrierColor }) { showGeneralDialog( context: context, pageBuilder: (BuildContext buildContext, Animation<double> animation, Animation<double> secondaryAnimation) { final Widget pageChild = child ?? Builder(builder: builder); return SafeArea( child: Builder( builder: (BuildContext context) { return pageChild; } ), ); }, barrierDismissible: barrierDismissible, barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, barrierColor: barrierColor, transitionDuration: const Duration(milliseconds: 150), transitionBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) { return FadeTransition( opacity: CurvedAnimation( parent: animation, curve: Curves.easeOut, ), child: child, ); }, ); } }
Flutter 关闭弹框并finish掉当前页面
场景描述:
在一个用户登录退出的场景模式下,并关闭掉当前页面,场景可能类似如下:
如图,当我们点击确定退出按钮,去请求接口,请求成功后,关闭当前dialog,然后再退出当前页面。
setting_page.dart
// 弹框 void showLoginOutDialog() { showDialog( context: context, barrierDismissible: false, // 点击外部不消失 builder: (BuildContext context){ return CommonDialog( title: "确定退出当前账号?", onNavClickListener: (){ print("onNavClickListener "); Navigator.of(context).pop(1); }, onPosClickListener: (){ print("loginaa "); Navigator.of(context).pop(1); _loginOut(); }, ); } ); } // 退出网络请求,这里的pop("login_out")为标志,进行退出后页面的刷新操作。 void _loginOut() async{ DataUtils.loginOut().then((res){ print("res $res"); if (res) { ToastUtil.showBottomToast("退出成功"); Navigator.of(context).pop("login_out"); }else { ToastUtil.showBottomToast("退出失败"); } }).catchError((onError){ print("onError $onError"); }); }
页面弹出/返回时 return Future.value(false) 的作用
当我们在 flutter 应用中,跳转到其他 app 或者返回桌面时会这么调用
同样的我们退出当前页面时,调用 Navigator.pop(context) 后同样也会调用 return Future.value(false) 这是为什么呢?
原因
首先我们要知道不调用会怎么样?
不调用会怎么样
- 如果我们在调用 Navigator.pop(context, false) 之后
- 使用的是 return Future.value(true);
- 那么按下后退按钮后,应用程序将显示黑屏,logcat中没有错误。
为什么使用
- 当我们使用 Navigator.pop(context),Future.value(true); 手动导航,会触发另一个无法完成的弹出窗口
- 这是由于当前已经存在页面,所以这会使应用程序崩溃。
- 这时由于 OnWillPop 需要返回,因此通过使用 return Future.value(false);告诉 OnWillPop 我们在此处处理页面的关闭