赞
踩
用于在屏幕上显示浮层的组件
/// Overlay的设计思路 class Overlay extends StatefulWidget //可以看出Overlay是一个有状态的widget,直接看对应的OverlayState里面的实现。 final List<OverlayEntry> _entries = <OverlayEntry>[]; //OverlayState里面维护OverlayEntry的列表,那么OverlayEntry是什么? /// 在OverlayEntry注释里有这样一段: Because an [Overlay] uses a [Stack] layout, overlay entries can use [Positioned] and [AnimatedPositioned] to position themselves within the overlay. //这句话可以理解为Overlay包含一个Stack布局,每个浮层都是一个Positioned widget,可以添加到Stack中。 又因为Stack是可以覆盖的,所以就能做出浮窗等效果。 /// 至此已经明白了一个基本思路:OverlayEntry是浮窗的UI,而OverlayState通过维护OverlayEntry来显示对应的UI。那么怎么绘制的呢? Widget build(BuildContext context) { ... for (int i = _entries.length - 1; i >= 0; i -= 1) { ... children.add(_OverlayEntryWidget( key: entry._key, entry: entry, )); // 至此,在build里,通过_OverlayEntryWidget这个实际绘制UI的widget绘制,然后add给children,children在给真正绘制的UI的地方(这就不继续跟下去了,这里着重发现Overlay的设计思路) /// 总结:OverlayEntry是浮窗的UI,而OverlayState在build遍历OverlayEntry的列表来绘制每一个OverlayEntry。
class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( body: Column( children: [ ElevatedButton( onPressed: () => btn1(context), child: const Text("btn1"), ), ], ), ), ); } void btn1(BuildContext context) { /// 步骤1:绘制OverlayEntry的UI OverlayEntry? overlayEntry; overlayEntry = OverlayEntry(builder: (context) { return Positioned( // 指定位置 left: 0, top: 100, child: GestureDetector( // 点击删除 onTap: () { overlayEntry?.remove(); }, // 背景随机色 child: Container( width: 100, height: 100, color: Colors.red, child: const Center( // 提示文字 child: Text( "这是一个 overlay 浮层, 点击关闭", style: TextStyle( color: Colors.white, fontSize: 10, decoration: TextDecoration.none, ), ), ), ), ), ); }); /// 步骤2:把OverlayEntry的添加给overlayState。overlayState自己就会去setState展示 OverlayState? overlayState = Overlay.of(context); overlayState.insert(overlayEntry); /// 步骤2:实际使用时通过Overlay.of(context)获得OverlayState要在dispose()时销毁 } }
OverlayEntry({
required this.builder, // 绘制UI
bool opaque = false, // 是否不透明的,设置为true,就会让当前屏幕除了UI,都被遮盖,因为不透明嘛
bool maintainState = false, //绘制的UI里如果没有用StatefulWidget,就设置为false,如果用了并且希望接收到外层的setState就设置为true
})
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。