Overlay
可以实现悬浮组件, 它内部由一个 Stack
构成, 相当于 Android 的 FrameLayout
.
用法:
// 创建OverlayEntry
Overlay entry = OverlayEntry(builder:(){/*在这里创建自己的widget*/});
// 往Overlay中插入OverlayEntry
Overlay.of(context).insert(overlayEntry);
// 调用entry自身的remove()方法,从所在的overlay中移除自己
entry.remove();
OverlayEntry builder 参数可以 return Positioned
或者 AnimatedPositioned
Widget 在 overlay 中定位自己的位置。
Overlay 继承于 StatefulWidget, Overlay.of(context)
表示向上查找 OverlayState 对象, 使用 OverlayState 对象来进行插入和移除子 widget 的操作. (如何查找? 使用了 InheritedWidget
)
- 可以自定义 Toast 以及其他悬浮组件
- 以及类似PopupWindow的弹窗效果
分析
WidgetsApp
我们构建 Flutter 时一般都用 MaterialApp
/CupertinoApp
作为顶层, 这两个 Widget 的内部包含了 WidgetsApp
, 通过查看 WidgetsApp 的源码发现:
GlobalKey<NavigatorState> _navigator; // <----- 声明
// ...
@override
void initState() {
super.initState();
_updateNavigator(); // <----- 初始化
// ...
}
// ...
void _updateNavigator() {
_navigator = widget.navigatorKey ?? GlobalObjectKey<NavigatorState>(this);
}
WidgetsApp 初始化时会创建一个 _navigator
, 类型为 GlobalKey<NavigatorState>
,而 NavigatorState
就是 Navigator
的状态对象.
Navigator
用于管理页面之间如何跳转,通常也可被称为导航管理,如果用户没有传入navigatorKey
,它会自动创建一个.
MaterialApp
/CupertinoApp
一般作为 Flutter App 的相对顶层 Widget, 所以每个 App 都会仅有一个用于路由管理的 Navigator
对象.
Navigator
继续到 Navigator
源码里,发现了个 _overlayKey
, 类型为 GlobalKey<OverlayState>
.
// ...1478行
final GlobalKey<OverlayState> _overlayKey = GlobalKey<OverlayState>();
// ...1576行
OverlayState get overlay => _overlayKey.currentState;
// ...2214行
@override
Widget build(BuildContext context) {
// ...
return Listener(
onPointerDown: _handlePointerDown,
onPointerUp: _handlePointerUpOrCancel,
onPointerCancel: _handlePointerUpOrCancel,
child: AbsorbPointer(
absorbing: false,
child: FocusScope(
node: focusScopeNode,
autofocus: true,
child: Overlay( // <----- 0.0
key: _overlayKey, // <----- ^.^
),
),
),
);
}
在 Navigator
的 build()
方法里发现 Navigator
就是使用 Overlay
做子 Widget 的! 在用法那里使用 Overlay.of(context)
获取到的应该就是这个 Overlay 的 State 对象了.
总结
MaterialApp / CupertinoApp 初始化的时候, 会创建一个唯一的 Navigator, Navigator 内部又会创建一个 Overlay.
每个页面都是 Navigator 管理的, 而 Overlay 内部由一个 Stack 构成, 所以 Overlay 可以实现悬浮组件, 让独立的 child widget 悬浮于其他 widget 之上的功能.