共计 6385 个字符,预计需要花费 16 分钟才能阅读完成。
Flutter Overlay 你用上了么
<img src=”https://ducafecat.oss-cn-beijing.aliyuncs.com/podcast/2023/05/019d70aac9f69a63abd4fb93d169de05.jpeg” alt=”Flutter overlay did you use it?” style=”width:90%;” />
前言
Flutter 中的 Overlay 是一个用于在屏幕上显示浮层的组件。它能够用来在应用程序中创立弹出窗口、提示框、菜单、对话框等等。
Overlay 通常用于在用户与应用程序交互时显示临时性的 UI 元素,例如:用户点击按钮时显示下拉菜单、用户长按屏幕时显示上下文菜单、显示正告或谬误音讯等等。
Overlay 通常蕴含一个 Stack 布局,每个浮层都是一个 Positioned widget,能够增加到 Stack 中。这样,能够将多个浮层叠加在一起,并管制它们的档次关系。
Flutter 中的 Overlay 能够让开发者轻松创立简单的 UI,同时还能够放弃应用程序的性能和响应度。
本文中提供的代码示例演示了如何在 Flutter 中应用 Overlay 制作工作覆盖层。Overlay 包含两个根本组件:OverlayState 和 OverlayEntry。OverlayState 治理所有 OverlayEntry,OverlayEntry 定义覆盖层中的内容。在示例中,OverlayEntry 蕴含一个带有文本和色彩的容器,能够在屏幕上显示。这些条目能够通过 OverlayState 的 insert 和 remove 办法增加和删除。
原文 https://ducafecat.com/blog/flutter-overlay-did-you-use-it
<img src=”https://ducafecat.oss-cn-beijing.aliyuncs.com/podcast/2023/05/15894a6d156e574b80aa96dc62a13740.png” alt=”image-20230518102503338″ style=”width:50%;” />
视频
https://www.bilibili.com/video/BV1qX4y1C7rb/
代码
https://github.com/ducafecat/flutter_develop_tips/tree/main/flutter_application_overlay
参考
https://api.flutter.dev/flutter/widgets/Overlay-class.html
https://api.flutter.dev/flutter/widgets/OverlayEntry-class.html
OverlayEntry
Overlay 通过将独立的子窗口小部件插入到重叠的堆栈中,使它们在其余窗口小部件之上“浮动”可视元素。笼罩容许每个小部件应用 OverlayEntry 对象治理它们在笼罩中的参加。
构造函数
OverlayEntry({
required this.builder,
bool opaque = false,
bool maintainState = false,
})
- builder:此属性用于此条目,并将在条目地位的笼罩中蕴含此构建器构建的小部件。
- opaque:此属性用于获取 bool 值,该值决定此条目是否阻止整个笼罩。如果条目申明为不通明,则为了提高效率,除非它们具备 maintainState 设置,否则笼罩将跳过在该条目上面构建条目。
- maintainState:如果您须要在
OverlayEntry
中应用有状态的小部件,那么您须要将maintainState
设置为 true,以便小部件能够放弃其状态并接管生命周期办法。如果您只是在OverlayEntry
中显示一个动态小部件,则能够将maintainState
设置为 false,以便小部件能够开释内存和资源,不会对性能产生过多影响。
OverlayEntry 办法
只有一个 OverlayEntry 的办法
- remove:此办法用于从覆盖层中删除此条目
OverlayState
Overlay 的以后状态用于将 OverlayEntries 插入覆盖层中。
OverlayState 办法
- debugIsVisible:此办法用于查看给定的 OverlayEntry 是否可见,并返回布尔值。
- insert:此办法用于将给定的 OverlayEntry 插入覆盖层中。
- insertAll:此办法用于获取 OverlayEntries 的 List,并将所有条目插入覆盖层中。您还能够指定上述和下述属性以阐明要插入条目标程序。
- rearrange:它能够重新排列以后在屏幕上叠加的所有小部件。具体来说,
rearrange
办法会将最初增加的OverlayEntry
小部件挪动到最下面,并将其余小部件挪动到上面。这能够用于确保最新的OverlayEntry
始终位于最下面,并且能够接管用户的触摸事件等。
步骤
第一步:成员变量
/// overlay 状态
OverlayState? overlayState;
/// overlay 层汇合
List<OverlayEntry> entriesList = [];
@override
void initState() {super.initState();
// 获取 overlay 状态
overlayState = Overlay.of(context);
}
@override
void dispose() {
// 销毁
overlayState?.dispose();
super.dispose();}
第二步:随机层显示
// 随机地位显示层
void showRandomOverlay(BuildContext context) {
// 随机色彩
final bgColor = Color.fromARGB(
255,
1 + Random().nextInt(254),
1 + Random().nextInt(254),
1 + Random().nextInt(254),
);
// 屏幕宽度
final screenWidth = MediaQuery.of(context).size.width;
// 随机屏幕高度
final randomHeight =
MediaQuery.of(context).size.height * Random().nextDouble();
OverlayEntry? overlayEntry;
overlayEntry = OverlayEntry(builder: (context) {
return Positioned(
// 指定地位
left: 0,
top: randomHeight,
child: GestureDetector(
// 点击删除
onTap: () {overlayEntry?.remove();
entriesList.remove(overlayEntry);
},
// 背景随机色
child: Container(
width: screenWidth,
height: 100,
color: bgColor,
child: Center(
// 提醒文字
child: Text("这是一个 overlay ${Random().nextInt(100)} 层, 点击敞开",
style: const TextStyle(
color: Colors.white,
fontSize: 20,
decoration: TextDecoration.none,
),
),
),
),
),
);
});
overlayState?.insert(overlayEntry);
entriesList.add(overlayEntry);
}
第三步:管制按钮
// 管制按钮
Widget _buildBtns() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// 随机新增
ElevatedButton(onPressed: () => showRandomOverlay(context),
child: const Text("随机新增"),
),
// 敞开所有
ElevatedButton(onPressed: () {for (final entry in entriesList) {entry.remove();
}
entriesList = [];},
child: const Text("敞开所有"),
),
// 随机排序
ElevatedButton(onPressed: () {
// 从屏幕上移除
for (final entry in entriesList) {entry.remove();
}
// 应用 Random 类创立随机数生成器
Random random = Random();
// 应用 List 的 sublist()办法创立一个新列表
List<OverlayEntry> shuffledEntries = entriesList.sublist(0);
// 调用 List 的 shuffle()办法,传入一个随机数生成器
shuffledEntries.shuffle(random);
// 插入界面
overlayState?.insertAll(shuffledEntries);
},
child: const Text("随机排序"),
),
],
);
}
最初:主视图显示
// 主视图
Widget _mainView() {
return Padding(padding: const EdgeInsets.only(top: 100),
child: Align(
alignment: Alignment.topCenter,
child: _buildBtns(),),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(body: _mainView(),
);
}
残缺代码
lib/overlay_view.dart
import 'dart:math';
import 'package:flutter/material.dart';
class OverlayUsePage extends StatefulWidget {const OverlayUsePage({super.key});
@override
State<OverlayUsePage> createState() => _OverlayUsePageState();
}
class _OverlayUsePageState extends State<OverlayUsePage> {
/// overlay 状态
OverlayState? overlayState;
/// overlay 层汇合
List<OverlayEntry> entriesList = [];
// 随机地位显示层
void showRandomOverlay(BuildContext context) {
// 随机色彩
final bgColor = Color.fromARGB(
255,
1 + Random().nextInt(254),
1 + Random().nextInt(254),
1 + Random().nextInt(254),
);
// 屏幕宽度
final screenWidth = MediaQuery.of(context).size.width;
// 随机屏幕高度
final randomHeight =
MediaQuery.of(context).size.height * Random().nextDouble();
OverlayEntry? overlayEntry;
overlayEntry = OverlayEntry(builder: (context) {
return Positioned(
// 指定地位
left: 0,
top: randomHeight,
child: GestureDetector(
// 点击删除
onTap: () {overlayEntry?.remove();
entriesList.remove(overlayEntry);
},
// 背景随机色
child: Container(
width: screenWidth,
height: 100,
color: bgColor,
child: Center(
// 提醒文字
child: Text("这是一个 overlay ${Random().nextInt(100)} 层, 点击敞开",
style: const TextStyle(
color: Colors.white,
fontSize: 20,
decoration: TextDecoration.none,
),
),
),
),
),
);
});
overlayState?.insert(overlayEntry);
entriesList.add(overlayEntry);
}
// 管制按钮
Widget _buildBtns() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// 随机新增
ElevatedButton(onPressed: () => showRandomOverlay(context),
child: const Text("随机新增"),
),
// 敞开所有
ElevatedButton(onPressed: () {for (final entry in entriesList) {entry.remove();
}
entriesList = [];},
child: const Text("敞开所有"),
),
// 随机排序
ElevatedButton(onPressed: () {
// 从屏幕上移除
for (final entry in entriesList) {entry.remove();
}
// 应用 Random 类创立随机数生成器
Random random = Random();
// 应用 List 的 sublist()办法创立一个新列表
List<OverlayEntry> shuffledEntries = entriesList.sublist(0);
// 调用 List 的 shuffle()办法,传入一个随机数生成器
shuffledEntries.shuffle(random);
// 插入界面
overlayState?.insertAll(shuffledEntries);
},
child: const Text("随机排序"),
),
],
);
}
// 主视图
Widget _mainView() {
return Padding(padding: const EdgeInsets.only(top: 100),
child: Align(
alignment: Alignment.topCenter,
child: _buildBtns(),),
);
}
@override
void initState() {super.initState();
// 获取 overlay 状态
overlayState = Overlay.of(context);
}
@override
void dispose() {
// 销毁
overlayState?.dispose();
super.dispose();}
@override
Widget build(BuildContext context) {
return Scaffold(body: _mainView(),
);
}
}
小结
本文提供了一个很好的介绍 Flutter Overlay 的概念和应用办法。无论是初学者还是有教训的开发人员,都能够从本文中取得新的常识和见解。如果你想在你的 Flutter 我的项目中实现工作覆盖层,本文是一个很好的终点。
© 猫哥
ducafecat.com
end
本文由 mdnice 多平台公布