用了手势监听的方式返回上一页,为什么不直接用BackButton,里面也调用了路由ma ymaybePop为什么点击没反应
来源:6-7 如何创建和使用Flutter的路由与导航?【边学边做】
IT小菜
2019-05-14
1回答
-
首先检查一下BackButton所在页面是不是被MaterialApp组件包裹了呢,被MaterialApp包裹的页面是无法通过BackButton组件返回到上一页的,将外层的MaterialApp去掉即可:
@override Widget build(BuildContext context) { return MaterialApp( ... home: Scaffold( appBar: AppBar( title: Text('BackButton点击没反应'), leading: BackButton(), ), ... } //改成 @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('BackButton点击没反应'), leading: BackButton()//外层不能有MaterialApp, ), ... }
BackButton被点击的时候会调用maybePop进行返回:
@optionalTypeArgs Future<bool> maybePop<T extends Object>([ T result ]) async { final Route<T> route = _history.last; assert(route._navigator == this); final RoutePopDisposition disposition = await route.willPop(); if (disposition != RoutePopDisposition.bubble && mounted) { if (disposition == RoutePopDisposition.pop) pop(result); return true; } return false; }
接下来说下一原理:
在上述代码中:
final RoutePopDisposition disposition = await route.willPop();
当BackButton被点击时,会通过route.willPop()决定是否可以返回到上一页,这里我们先看一下willPop()到底做了什么:
Future<RoutePopDisposition> willPop() async { return isFirst ? RoutePopDisposition.bubble : RoutePopDisposition.pop; }
willPop会判断当前页面是不是处于栈顶(当前MaterialApp中的第一个页面),如果是则返回RoutePopDisposition.bubble,所以说只有当前页面不是MaterialApp中的第一个页面时才能通过maybePop返回到上一页,在上述案例中,BackButton被放在了MaterialApp下的第一个页面中所以会出现BackButton点击无效的问题。
接下来在扩充下maybePop与pop的区别,它们的不同之处在于maybePop会多了一步向系统询问是否处理当前返回操作,当Route.willPop返回值为RoutePopDisposition.bubble时即交给系统处理,这里也简单介绍RoutePopDisposition三个枚举值:
pop 弹出路由,正常情况返回上一级
doNotPop 不弹出,沉默处理,很多时候出现在一些表单填写的情况,必须完成页面内容,或者提示用户点击第二次才能退出
bubble 交给系统处理,一般直接退出应用
简单来讲,pop()要比maybePop()的功能更强大些,pop()不管当前页面是不是处于栈顶都会使当前页面关闭,也可以返回到上一个MaterialApp中的页面,而maybePop()只能返回当前MaterialApp中的上一个页面。
注意:pop()这么强大但它有个副作用,如果当前页面已经处于栈顶并且前面没有其他MaterialApp的时候,调用pop()你会看到黑屏,这是因为在这种情况下pop()将应用中的唯一的一个页面关闭导致的,所以为了防止这个问题可以在调用pop()之前通过Navigator.canPop(context)判断下是不是还可以返回。
212019-05-15
相似问题