Flutter覆盖层管理插件x_overlay的使用
Flutter覆盖层管理插件x_overlay的使用
如果你觉得这个包对你有帮助,请在pub.dev上给它点赞!↗️
你的支持和鼓励激励我们继续改进和维护这个包。
感谢你认可我们的工作!👏👏
功能
轻松支持覆盖层
使用方法
自定义覆盖层数据
你可以通过继承扩展来自定义变量。
/// 定义
class MyOverlayData extends XOverlayData {
MyOverlayData({
required this.myVariable,
});
final String myVariable;
}
/// 转换
final overlayData = XOverlayData();
late MyOverlayData myOverlayData;
if (data is MyOverlayData) {
myOverlayData = data;
}
myOverlayData.myVariable;
定义一个 XOverlayController 对象
final overlayController = XOverlayController();
在你的应用主页面中使用 XOverlayPopScope
这将替换直接退出应用并返回到桌面,否则页面会被销毁。
MaterialApp(
...
home: XOverlayPopScope(
child: YourHomePage(),
),
)
在 MaterialApp 的 builder 中嵌套 XOverlayPage
- 在 builder 中读取覆盖层数据并返回覆盖层页面。
- 确保在 contextQuery 中返回正确的上下文。
- 默认情况下,点击覆盖层页面会返回到内容页面。因此,在 restoreWidgetQuery 中读取覆盖层数据并返回内容页面。
MaterialApp(
...
navigatorKey: widget.navigatorKey,
builder: (BuildContext context, Widget? child) {
return Stack(
children: [
child!,
/// 添加覆盖层页面在 MaterialApp.builder 中
XOverlayPage(
controller: overlayController,
contextQuery: () {
return widget.navigatorKey.currentState!.context;
},
restoreWidgetQuery: (
XOverlayData data,
) {
/// 默认情况下,点击覆盖层页面会返回到内容页面。
/// 因此,读取你的覆盖层数据,并返回你的内容页面
late MyOverlayData myOverlayData;
if (data is MyOverlayData) {
myOverlayData = data;
}
/// 然后恢复目标小部件
return ContentPage(
overlayController: overlayController,
/// 当从覆盖层页面返回时,可以同步在覆盖过程中更改的结果。
customVariable: myOverlayData.myVariable,
);
},
builder: (XOverlayData data) {
/// 读取你的覆盖层数据并返回覆盖层页面
late MyOverlayData myOverlayData;
if (data is MyOverlayData) {
myOverlayData = data;
}
return OverlayPage(
overlayController: overlayController,
/// 从内容页面读取的数据,并可能在覆盖过程中更改
customVariable: myOverlayData.myVariable,
);
},
),
],
);
},
)
在你的内容小部件中添加 XOverlayButton
或者自定义一个按钮并调用控制器的 overlay 方法。
XOverlayButton(
controller: widget.overlayController,
dataQuery: () {
/// 需要返回到覆盖层页面的数据
return YourOverlayData();
},
)
示例
以下是完整的示例代码:
import 'package:flutter/material.dart';
import 'package:x_overlay/x_overlay.dart';
class MyOverlayData extends XOverlayData {
MyOverlayData({
required this.myVariable,
});
final String myVariable;
}
void main() {
WidgetsFlutterBinding.ensureInitialized();
final navigatorKey = GlobalKey<NavigatorState>();
runApp(MyApp(
navigatorKey: navigatorKey,
));
}
class MyApp extends StatefulWidget {
final GlobalKey<NavigatorState> navigatorKey;
const MyApp({
required this.navigatorKey,
super.key,
});
[@override](/user/override)
State<StatefulWidget> createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
/// 1/4. 定义一个 XOverlayController 对象
final overlayController = XOverlayController();
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: widget.navigatorKey,
title: 'Flutter Demo',
color: Colors.white,
/// 2/4. 替换直接退出应用并返回到桌面,否则页面会被销毁。
home: XOverlayPopScope(
child: HomePage(
overlayController: overlayController,
),
),
builder: (BuildContext context, Widget? child) {
return Stack(
children: [
child!,
/// 3/4. 在 MaterialApp.builder 中添加覆盖层页面
XOverlayPage(
controller: overlayController,
contextQuery: () {
return widget.navigatorKey.currentState!.context;
},
restoreWidgetQuery: (
XOverlayData data,
) {
/// 默认情况下,点击覆盖层页面会返回到内容页面。
/// 因此,读取你的覆盖层数据,并返回你的内容页面
late MyOverlayData myOverlayData;
if (data is MyOverlayData) {
myOverlayData = data;
}
/// 然后恢复目标小部件
return ContentPage(
overlayController: overlayController,
/// 当从覆盖层页面返回时,可以同步在覆盖过程中更改的结果。
customVariable: myOverlayData.myVariable,
);
},
builder: (XOverlayData data) {
/// 读取你的覆盖层数据并返回覆盖层页面
late MyOverlayData myOverlayData;
if (data is MyOverlayData) {
myOverlayData = data;
}
return OverlayPage(
overlayController: overlayController,
/// 从内容页面读取的数据,并可能在覆盖过程中更改
customVariable: myOverlayData.myVariable,
);
},
),
],
);
},
);
}
}
class HomePage extends StatefulWidget {
const HomePage({
super.key,
required this.overlayController,
});
final XOverlayController overlayController;
[@override](/user/override)
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
/// 防止UI因文本编辑器移动
resizeToAvoidBottomInset: false,
body: SafeArea(
child: Stack(
children: [
Container(color: Colors.white),
const Align(
alignment: Alignment.topCenter,
child: Text("Home Page"),
),
Center(child: contentButton()),
],
),
),
);
}
Widget contentButton() {
return ValueListenableBuilder<XOverlayPageState>(
valueListenable: widget.overlayController.pageStateNotifier,
builder: (context, overlayPageState, _) {
return ElevatedButton(
onPressed: () {
if (XOverlayPageState.overlaying == overlayPageState) {
/// 在覆盖过程中,直接恢复内容页面
widget.overlayController.restore(context);
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ContentPage(
overlayController: widget.overlayController,
),
),
);
}
},
child: const Text("Content Page"),
);
},
);
}
}
class ContentPage extends StatefulWidget {
final XOverlayController overlayController;
/// 当从覆盖层页面返回时,可以设置在覆盖过程中更改的结果。
final String? customVariable;
const ContentPage({
super.key,
required this.overlayController,
this.customVariable,
});
[@override](/user/override)
State<ContentPage> createState() => _ContentPageState();
}
class _ContentPageState extends State<ContentPage> {
final textController = TextEditingController();
[@override](/user/override)
void initState() {
super.initState();
textController.text = widget.customVariable ?? 'Custom Variable';
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Container(color: Colors.blue),
const Align(
alignment: Alignment.topCenter,
child: Text("Content Page"),
),
Positioned(
top: 10,
left: 10,
child:
/// 4.1/4. 你可以直接使用 XOverlayButton
XOverlayButton(
buttonSize: const Size(30, 30),
controller: widget.overlayController,
dataQuery: () {
/// 需要返回到覆盖层页面的数据
return MyOverlayData(
myVariable: textController.text,
);
},
),
),
Positioned(
top: 10,
right: 10,
child: SizedBox(
height: 50,
child: ElevatedButton(
/// 4.2/4. 或者自定义一个覆盖按钮并调用API
/// 使用 `overlayController.overlay(context, data: MyOverlayData);`
/// 在按钮的 onClick 事件上覆盖当前目标小部件
onPressed: () {
/// 需要返回到覆盖层页面的数据
final overlayData = MyOverlayData(
myVariable: textController.text,
);
/// 缓存数据并覆盖目标小部件
widget.overlayController.overlay(
context,
data: overlayData,
);
},
child: const Text("Overlay Button"),
),
),
),
Center(child: TextField(controller: textController))
],
),
),
);
}
}
class OverlayPage extends StatefulWidget {
final String customVariable;
final XOverlayController overlayController;
const OverlayPage({
super.key,
required this.overlayController,
/// 从内容页面读取的数据,并可能在覆盖过程中更改
required this.customVariable,
});
[@override](/user/override)
State<OverlayPage> createState() => _OverlayPageState();
}
class _OverlayPageState extends State<OverlayPage> {
final textController = TextEditingController();
[@override](/user/override)
void initState() {
super.initState();
textController.text = widget.customVariable;
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
/// 防止UI因文本编辑器移动
resizeToAvoidBottomInset: false,
body: SafeArea(
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(10),
),
child: Stack(
children: [
const Align(
alignment: Alignment.topCenter,
child: Text("Overlay Page"),
),
Center(
child: TextField(
controller: textController,
textAlign: TextAlign.center,
onChanged: (text) {
widget.overlayController.updateData(
MyOverlayData(myVariable: text),
);
},
),
),
],
),
),
),
);
}
}
更多关于Flutter覆盖层管理插件x_overlay的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter覆盖层管理插件x_overlay的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于Flutter中的x_overlay
插件(假设这是一个用于管理覆盖层的第三方插件,尽管这不是一个官方或广泛认知的插件名,但我会基于假设给出一个通用的覆盖层管理示例),以下是一个可能的代码案例来展示如何使用一个覆盖层管理插件。请注意,具体实现可能会根据插件的实际API有所不同,以下代码仅供参考。
首先,假设x_overlay
插件提供了一个OverlayManager
类来管理覆盖层,并且有一个showOverlay
方法来显示覆盖层。以下是一个简单的示例代码:
1. 添加依赖
首先,确保在pubspec.yaml
文件中添加了x_overlay
插件的依赖(这里假设插件名为x_overlay
,实际使用时请替换为正确的插件名):
dependencies:
flutter:
sdk: flutter
x_overlay: ^latest_version # 替换为实际版本号
2. 导入插件并使用
在你的Flutter应用中,导入x_overlay
插件并使用它。以下是一个完整的示例,包括如何在按钮点击时显示一个覆盖层:
import 'package:flutter/material.dart';
import 'package:x_overlay/x_overlay.dart'; // 假设这是插件的导入路径
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Overlay Manager Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: OverlayDemoScreen(),
);
}
}
class OverlayDemoScreen extends StatefulWidget {
@override
_OverlayDemoScreenState createState() => _OverlayDemoScreenState();
}
class _OverlayDemoScreenState extends State<OverlayDemoScreen> {
final OverlayManager _overlayManager = OverlayManager();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Overlay Manager Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
_showOverlay(context);
},
child: Text('Show Overlay'),
),
),
);
}
void _showOverlay(BuildContext context) {
// 假设OverlayManager有一个showOverlay方法,接收一个OverlayEntry和一个context
_overlayManager.showOverlay(
context,
OverlayEntry(
builder: (context) => Material(
elevation: 4.0,
child: Container(
width: double.infinity,
height: 200,
color: Colors.white,
child: Center(
child: Text('This is an overlay!'),
),
),
),
),
);
}
}
// 假设这是插件中定义的OverlayManager类(实际上这个类应该由插件提供)
class OverlayManager {
OverlayState? _overlayState;
void showOverlay(BuildContext context, OverlayEntry overlayEntry) {
_overlayState ??= Overlay.of(context)!;
_overlayState!.insert(overlayEntry);
}
// 可以添加更多管理覆盖层的方法,如隐藏、移除等
}
注意事项
-
插件API:上面的代码是基于假设的
OverlayManager
类及其showOverlay
方法。实际使用时,请查阅x_overlay
插件的文档以了解正确的API用法。 -
OverlayEntry管理:在实际应用中,你可能需要管理多个
OverlayEntry
,例如隐藏或移除它们。这通常涉及到在OverlayEntry
上调用remove()
方法。 -
错误处理:确保处理可能的空值或异常,特别是在调用插件方法时。
-
插件版本:检查插件的最新版本和更新日志,以确保你的代码与插件的最新API兼容。
由于x_overlay
不是一个官方或广泛认知的插件名,上述代码是一个基于假设的示例。如果x_overlay
是一个特定的第三方插件,请查阅其官方文档以获取准确的用法示例。