在平常的需求开发中,可能会遇到需要在app中添加一个全局的视图,比如单点登录提示的全局弹框,音乐播放的悬浮控制按钮等。简单看了下在Flutter中的实现思路,记录一下。
这篇文章拿稍微复杂一点的音乐播放悬浮控制按钮作为实现示例,主要内容包含两点:
1.顶层视图的显示
2.组件拖动+两侧吸附效果
1.顶层视图显示
在flutter中实现顶层视图显示,是通过Overlay这个组件来实现的,这个组件的官方解释如下(仔细看官方解释,真的很重要,尤其是最后一句):
/// A [Stack] of entries that can be managed independently.
///
/// Overlays let independent child widgets "float" visual elements on top of
/// other widgets by inserting them into the overlay's [Stack]. The overlay lets
/// each of these widgets manage their participation in the overlay using
/// [OverlayEntry] objects.
/// Rather than creating an overlay, consider using the overlay that is
/// created by the [WidgetsApp] or the [MaterialApp] for the application.
Overlay的本质是“float(悬浮)”在其他组件上的Stack(组件的本质是Stack,所以我们想要添加的全局组件,就可以通过Position()控制位置啦(* ̄︶ ̄)),这个Stack可添加的子组件只能是OverlayEntry类型,所以当我们想要创建一个悬浮在全局的组件时,我们应该想办法拿到Overlay组件的实例,然后创建OverlayEntry,添加进Overlay。
那该怎么获取Overlay呢,最开始我以为可以通过Overlay.of(context)方法获取,但是我用这种方法获取之后,发现当我退出创建此悬浮组件的页面时,此context也会销毁,所以此方法不可取(哎……其实就是没有仔细看官方的解释,上面解释中的最后一句,已经给出答案(⊙︿⊙))。官方文档已经说了,最好使用WidgetsApp或MaterialApp的Overlay,按官方指使,获取Overlay的方法如下:
//首先为顶层视图创建一个key,通过key对象获取OverlayState
class MyApp extends StatelessWidget {
//通过顶层视图的key,可以获取OverlayState对象
static GlobalKey<NavigatorState> navigatorKey = new GlobalKey();
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Float Widget Demo',
navigatorKey: navigatorKey,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: "首页",),
);
}
}
1.获取overlayState
MyApp.navigatorKey.currentState.overlay;
2.获取到overlayState对象,创建我们自己的视图,添加进去:
//展示悬浮组件
showFloatWidget() {
OverlayEntry overlayEntry = new OverlayEntry(builder: (context) {
return Positioned(top: 100, left: 20, child: buildFloatWidget());
});
MyApp.navigatorKey.currentState.overlay.insert(overlayEntry);
//保存这个引用,**用于清除这个组件**
entryHolder = overlayEntry;
}
至此我们已经自己添加了一个全局悬浮组件,拖动加两侧吸附实现比较简单,之后再更新。